Showing posts with label XML. Show all posts
Showing posts with label XML. Show all posts

Tuesday, 20 March 2012

Creating a Flash app with a PHP script to upload webcam images to Wordpress

This month's challenge is to build a flash application that is able to take a photo, upload it, and insert it into a wordpress post so that posts can be easily edited later. (AND ALL WITHIN ONE OR TWO WEEKS!) I am building this for a museum exhibition that has just opened and it is going to be a kiosk with a large touchscreen that will be moved around from venue to venue, collecting photos of people's pockets and stuff, and then digitally archiving them, while allowing one to also tag it collaboratively after that.

I am not a PHP developer although I understand PHP sufficiently well in order to make it do what I need to do, so if anyone more technically inclined can tell me if this is an efficient way to proceed with this, I would be glad to hear if there are other ways to do this!

1. Uploading Image to server


I used php's mktime to generate a unique number for each photo's filename. Each photo was encoded using JPGEncoder in flash, and then using urlLoader I sent it to my php file, which saved it onto my server with a filename derived from the mktime number.

After that, the posts were pushed to wordpress with the help of Incutio XML-RPC Library for PHP. You can post to wordpress with a php script with the help of xml-rpc. The following examples are my own mashup of bits and pieces found online, the most instructive guide being this entry: WordPress XMLRPC – Posting Content From Outside WordPress Admin Panel

<?php
if(isset($GLOBALS["HTTP_RAW_POST_DATA"])){
 
 $jpg = $GLOBALS["HTTP_RAW_POST_DATA"];
 $img = $_GET["img"];
 $filename = "images/booth_" . mktime(). ".jpg";
 file_put_contents($filename, $jpg);
 
require_once("IXR_Library.php.inc");
 
$client->debug = true; //Set it to false in Production Environment 
$title='Pocket No. '.mktime(); // $title variable will insert your blog title 
$body='<img src="http://yourdomain.org/'.$filename.'">'; // $body will insert your blog content (article content)
$category="pocket"; // Comma seperated pre existing categories. Ensure that these categories exists in your blog.
$keywords="keyword1, keyword2, keyword3"; // Comma Seperated keywords
$customfields=array('key'=>'Author-bio', 'value'=>'Author Bio Here'); // Insert your custom values like this in Key, Value format
 
    $title = htmlentities($title,ENT_NOQUOTES,$encoding);
    $keywords = htmlentities($keywords,ENT_NOQUOTES,$encoding);
 
    $content = array(
        'title'=>$title,
        'description'=>$body,
        'mt_allow_comments'=>0,  // 1 to allow comments
        'mt_allow_pings'=>0,  // 1 to allow trackbacks
        'post_type'=>'post',
        'mt_keywords'=>$keywords,
        'categories'=>array($category),
  'custom_fields' =>  array($customfields)
    );
 
// Create the client object
$client = new IXR_Client('http://yourdomain.org/xmlrpc.php');
$username = "admin"; 
$password = "password"; 
$params = array(0,$username,$password,$content,true); // Last parameter 'true' means post immediately, to save as draft set it as 'false'
 
// Run a query for PHP
if (!$client->query('metaWeblog.newPost', $params)) {
    die('Something went wrong - '.$client->getErrorCode().' : '.$client->getErrorMessage());
}
else
    echo "Article Posted Successfully";
    
} else{
 echo "Encoded JPEG information not received.";
}
?>

2. Retrieving images to put into gallery


This php script will retrieve the last 10 entries in your wordpress and help format them into an xml sheet that you can use in flash to display wordpress entries and images in a flash gallery.

<?php
set_time_limit(0);
require_once("IXR_Library.php.inc"); 
// Echo the header (XML)
header("Content-Type: application/xml;charset=ISO-8859-1");
echo '<?xml version="1.0" encoding="ISO-8859-1"?>' . "\r\n";
echo "<GALLERY>\r\n"; 

// Prepare the XML file
$client->debug = true; // Set it to false in Production Environment
 
// Create the client object
$client = new IXR_Client('http://artsciencepocketbooth.org/xmlrpc.php');
$username = "admin"; 
$password = "password"; 
$params = array(0,$username,$password,10); // Last Parameter tells how many posts to fetch
 
// Run a query To Read Posts From Wordpress
if (!$client->query('metaWeblog.getRecentPosts', $params)) {
    die('Something went wrong - '.$client->getErrorCode().' : '.$client->getErrorMessage());
} 
$myresponse = $client->getResponse();
$i=0; ?>

<?php 
//foreach ($myresponse as $key => $value)
foreach ($myresponse as $res)
{ 
 
  if($res['post_status']!="draft"){
   //$times = new IXR_Date(); ?>
     <image id ='<?php echo $i+1; ?>' postid='<?php echo $res['postid']; ?>' title='<?php echo $res['title']; ?>' keywords='<?php echo $res['mt_keywords']; ?>'/>
<?php $i++; } } ?>
<?php echo "</GALLERY>"; ?>


The resulting XML file will look like this:
Screen shot 2012-03-21 at PM 08

3. Tagging images in gallery




PHP: Creating automatic XML Sheet from ALL images within a folder

If you need to create an XML sheet from all the photos within one folder, this is a script you can use to create one! It will include any image with a image-related file extension. This is my script which I have customised for my own needs based on notes and tutorials found online.

<?php
// Set which extensions should be approved in the XML file
$extensions = array
(
  'jpg', 'JPG',
  'png', 'PNG',
  'gif', 'GIF',
  'bmp', 'BMP'
);
 
// Echo the header (XML)
header("Content-Type: application/xml;charset=ISO-8859-1");
 
// Prepare the XML file
echo '<?xml version="1.0" encoding="ISO-8859-1"?>' . "\r\n";
echo "<GALLERY>\r\n";
 
// Get the files from the current directory
if (file_exists ("./"))
{
  if (is_dir ("./"))
  {
    $dh = opendir ("./") or die (" Directory Open failed !");
    
    // Prepare the images array
    $imgs = array();
    while ($file = readdir ($dh))
    {
      // Only get the files ending with the correct extension
      if ( in_array( substr($file, -3), $extensions ) )
      {
        array_push($imgs, $file);
      }
    }
  Closedir ($dh);
  }
  
  // Sort the array
  sort($imgs);
  
  foreach ($imgs as $img)
  {
    // Return all images in XML format
    echo ('   <image FULL="/images/' . $img . '" THUMB="/images/' . $img . '" />');
    echo "\r\n";
  }
}
echo "</GALLERY>";
?>



OOP & PHP?


there is an interesting article here that argues for OOP in PHP. i admit even in flash sometimes when doing something quick dirty for example i would use global code instead instead of encapsulation. but i guess i find the analogies arguing in favour of OOP rather interesting.

Monday, 23 January 2012

Traversing XML structures - Loops

I am working on a AS3 project with an XML data sheet and this week I figured out another solution to traversing the structure in a better fashion...

<?xml version="1.0" encoding="utf-8"?>
<TIMELINE>
 <YEAR NAME="2000">
  <ARTICLE>
   <MONTH>January</MONTH>
   <NAME>Lorem Ipsum</NAME>
   <DESCRIPTION>Lorem Ipsum is simply dummy text.</DESCRIPTION>
   <IMAGE>image1.jpg</IMAGE>
  </ARTICLE>
  <ARTICLE>
   <MONTH>December</MONTH>
   <NAME>Ipsum Lorem</NAME>
   <DESCRIPTION>Lorem Ipsum is simply dummy text.</DESCRIPTION>
   <IMAGE>image2.jpg</IMAGE>
  </ARTICLE>  
 </YEAR>
 <YEAR NAME="2003">
  <ARTICLE>
   <MONTH>April</MONTH>
   <NAME>Ipsum Lorem Ipsum</NAME>
   <DESCRIPTION>Lorem Ipsum is simply dummy text.</DESCRIPTION>
   <IMAGE>image3.jpg</IMAGE>
  </ARTICLE>  
 </YEAR>
</TIMELINE>

Basically, in my XML sheet, there were years, and within those years there could be more than one article. Some years had numerous articles. Some years had only one article.

myXML.*.*.length();

When I traced something like this, I would get the total number of articles. I could also traverse all the articles as if the year was not of consequence and all the articles were just being counted and assigned numbers in order from 0 onwards.

myXML.*.ARTICLE[articleNum].DESCRIPTION.toString();

The quandrary was that I needed to be able to scroll through all the articles chronologically but I needed to be able to tell what year it was from, according to the article number (which was now effectively independent from the year), and also be able to find out the article number within that year alone, rather than as a whole.

The solution I came up with: Use a loop to check for number of articles in all previous years, add them up so i can subtract it from the full number of articles. This gives you the article number within that year alone, instead of the article number within the entire "timeline" sheet.

var g:Number = 0;
//myXML.*.ARTICLE[articleNum].parent().childIndex() is year index for that article
while (g < myXML.*.ARTICLE[articleNum].parent().childIndex())
   {
        //myXML.YEAR[g].*.length() is the number of articles in g year
        articleNumContainer += myXML.YEAR[g].*.length();
        g += 1;
   }
// one is added to articleNum cos it actually starts at zero
articleNumberWithinYear = (articleNum + 1) - articleNumContainer;



Flash AS3 and SoThink SWF Decompiler

While saving my work, I had an error and lost the FLA while fortunately, having first published a perfect SWF. If you are saving your work in Flash and Flash crashes before it saves, it often causes your FLA to completely disappear. Always backup your work periodically. Thus I was forced to decompile my own code with SoThink SWF Decompiler to recover my work into an FLA file (for speed) but I also realised that it had decompiled it in a different way from how I had originally coded it. It was easy to figure out and I recovered my entire file within an hour to almost the exact way I had originally coded it. Here are some notes on what I noticed about how it had changed my code in the process of decompiling from swf to fla.
  1. All variables that are randomly declared all over the code are collected and put at the top of the code.
  2. New variables are given names like "_loc_2" or "_loc_3". Anything with many brackets is also assigned various variable names for different parts of the equation, and then a few of these temporary functions are added up together instead.
  3. All for loops are turned into while loops.
  4. "this." is added to any objects referred to on the main timeline
  5. It also makes use of the rather uncommon addFrameScript, which adds script to movieclips in AS3. If you leave bits of code outside functions by mistake (eg stage display items), it might group them together in a function called frame1.
  6. It adds the "end function" comment at the end of functions.
Example of typical while loop as decompiled in SoThink:
while (t < max_T_Number)
            {
                // do this
                t = (t + 1);
            }
Example of typical addFrameScript function as decompiled in SoThink:
public function MainTimeline()
        {
            addFrameScript(0, this.frame1);
            return;
        }// end function

        function frame1()
        {
            stage.scaleMode = StageScaleMode.SHOW_ALL;
            stage.align = StageAlign.TOP_LEFT;
            stage.displayState = StageDisplayState.FULL_SCREEN;
        }// end function
}

Although the decompiler is perhaps not the most ethical way of accessing other people's source code, I think the decompiler still makes an excellent learning tool for flash. When I have more time I will download more swfs or analyse more of my old swfs to see if the conditions listed above are consistently true.

Sunday, 8 January 2012

Traversing XML structures in AS3

There may come a time when one has to traverse some XML data....

Alright, so maybe never. But let's just pretend that the ability to sort XML data might be of some use to someone out there one day! After working on a project this week, this is what I figured out about traversing XML structures.


// load XML file into Flash
var myNewXML:XML;
var myNewXMLLength:Number;
var myNewLoader:URLLoader = new URLLoader();
myNewLoader.load(new URLRequest("xml/singapore.xml"));
myNewLoader.addEventListener(Event.COMPLETE, processmyNewXML);
function processmyNewXML(e:Event):void{
myNewXML = new XML(e.target.data);
myNewXMLLength = myNewXML.*.length();
//trace(myNewXML); // traces the ENTIRE xml sheet
//trace(myNewXMLLength); // traces the number of items in xml sheet
//trace(myNewXML.row[0]); // traces the first row
//trace(myNewXML.row[1]); // traces the second row
//trace(myNewXML.row[0].name); // traces the first row's name field
}

// creating a new XMLList to sort and loop through specific category filters
var myNewXMLList:XMLList = myNewXML.row.(category == "Ind" && type == "Pte");
for (var i:int = 0; i < myNewXMLList.length(); i++)
{
var myNewXMLElement:XML = myNewXMLList[i];
//trace(myNewXMLElement) // traces xml list of only the filtered items
//trace(i + ": " + myNewXMLElement.name); // trace the number and name
}

// checking for a value
if ("myValue" in myNewXMLList) {
trace("myValue exists in my XMLList");
}

/*
Other useful operators to use to traverse XML:
.parent();
.childIndex();
.length();
.toString();
.firstChild();
.nextChild();

You can also use a combination in a chain to find specific fields
*/

Q: Should you put the XML data into an Array before sorting it?

A: There isn't a real need to put XML into an Array for handling in AS3. Apparently ECMAScript (which includes Actionscript, Javascript, and JScript) now has native XML support (E4X), allowing XML to be treated as its various primitive parts, rather than a seperate object on its own.

I also wondered if I should put it in an array and sort it, as I initially didnt know how to sort for combinations of categories on different "levels". But in the end, it seems that it is not necessary to put your values into an array because there are certainly ways to sort and loop it through in the form of an XMLList. You could potentially create different XMLLists from the same XML file that has been loaded.

Q: How does one export Excel to XML on Microsoft Excel for Mac?

A: WELL, YOU CAN'T. It seems as if every single version of Microsoft Excel for Mac (including Excel 2011) is tragically unable to export XLS files into XML directly. It is said online that Windows Excel has both the Visual Basic editor and the magical XML function that Mac Excel is inexplicably bereft of. Excel 2007 for example, has no macros or VB editor at all, rendering it completely pointless. Why was such a simple and basic function omitted from all the Mac versions of Excel? As for alternatives like OpenOffice and NeoOffice, let's not even go there since they always crash on my Mac.

So my final solution? I saved all my XLS files to CSV (comma-seperated values), and then I used an opensource online tool called Mr Data Convertor to convert it to XML. OPENSOURCE WIN.

Q: How do I install an open source Syntax Highlighter?

A: You only need to add a little snippet to get a syntax highlighter running on your page. For the benefit of this post I also installed Alex Gorbatchev's syntax highlighter, an open source code syntax highlighter which can autoformat nearly any common programming language in blogger or your own site. If you are in the habit of posting code then this highlighter and HTML encoder may come in handy for converting all your pointy brackets into their HTML tags.