Working with Pydio (formally Ajaxplorer) in PHP - Part 1

If you've been in the market for open source cloud file sharing software, similar to Dropbox and Box, you may have come across Pydio(formally Ajaxplorer). It's an easy to install and use piece of software.

Pydio released version 6.0 on December 2, 2014. If you are a developer, Pydio comes with a straight forward Server-side API; however, the documentation is not so easy to read and understand (Pydio Server-side API Documentation). Today we are going over accomplishing some basic use of the API.

For this example I created a class that I named Pydio. These series of posts will show how to list files and folders from a workspace , upload a file, and download a file.

I started by setting some constants such as the URL of my Pydio instance and the name of the API functions I will be calling. Replace "mypydiourl.com" with the address of your Pydio instance, and "workspace" with the name of the workspace you wish to utilize.

class Pydio{
    const BASEURL = "http://mypydiourl.com/api/workspace/";
    const LS = "ls/";
    const DOWNLOAD = "download/";
    const UPLOAD = "upload/input_stream/";
    const UPWD = "username:password";
    private $folder = "";

    public function __construct($f){
        $this->folder = $f . "/";
    }

In my example I am accessing the same workspace for all my operations. If you want to make your code more general make the following changes:

//Change
const BASEURL = "http://mypydiourl.com/api/";

//Add
private $workspace;

//Change
public function _construct($w, $f)
{
    $this->workspace = $w;
    $this->folder = $f;
 }

Next, I created a function call prepareURL. All this function does is make sure the folder name is URL friendly (urlencode();)
NB: If your workspace name is not URL friendly, it must also be urlencode.

private function prepareURL($dir)
{
    $url = explode('/', trim($dir));

    //url encodes each section of the path passed in
    for($i = 0; $i < count($url); $i++)
        $url[$i]= urlencode(trim($url[$i]));
    return implode("/", $url);
}

The next step is to create the function that will perform the list function. The post to the Pydio API will be made using CURL. With the newest version of the Pydio API user authentication can occur when making the specific function call. Ajxp-Force-Login: true is added to force login with the call. Leaving this out may cause the call to fail because the user is not authenticated.

public function listd($dir){   
    $listing = array();
    $urlDir = $this->prepareURL($dir);
    $process = curl_init(trim(self::BASEURL . self::LS . $this->folder . $urlDir ));

    curl_setopt($process, CURLOPT_HTTPHEADER, array("Content-Type: application/xml", "Ajxp-Force-Login: true"));
    curl_setopt($process, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($process, CURLOPT_USERPWD,   self::UPWD );
    $return = curl_exec($process);
    curl_close($process);

Pydio returns a number of fields in XML format. I am using several of these fields to create an object that I will pass to me GUI. Below is the output of what Pydio returns, when I access my 'Test' repository which has 2 folders and 1 file in it.

    $xml = new SimpleXMLElement($return);
    $tree = $xml->children();

    $parent = $xml->attributes();
    $parent = get_object_vars($parent);

    //Adds to Parent Directory to the result
    array_push($listing, array("parent"=> $parent['@attributes']['filename'], "name" => $parent['@attributes']['text']));

    foreach($tree->tree as $node)
    {
        $node = get_object_vars($node);
        $temp = array(
            "name"     =>   $node['@attributes']['text'],
            "path"     =>   $node['@attributes']['filename'],
            "is_file"  =>   $node['@attributes']['is_file'],
            "modified" =>   $node['@attributes']['ajxp_relativetime'],
            "mimetype" =>    $node['@attributes']['mimestring'],
            "size"     =>   $node['@attributes']['bytesize']
            );

        array_push($listing, $temp);
    }           
    return $listing;
}

Next, I will show an example of a stylized output. The example is using Bootstrap 3, Slim Scroll JS, and Font-Awesome. You can implement the interface using JavaScript and PHP or pure PHP. I suggest JS and PHP to make changing directories easier.
JavaScript:

 $(document).ready(function() {
     $('#scrollWrapper').slimScroll({
      height: '340px'
      });

    getFileList('');
});

function getFileList(dir)
  {
      var client = "Test"; //name of repository
      $.ajax({
          url: "data/FileHandler.php",
          type: 'post',
          dataType: "json",
          data:{
              method: 'getFileListing',
              dir: dir,
              client: client
          },
          success: function(ret){
              var files = ret;
              var str = '';

              for(i in files)
              {
                  if(typeof(files[i]['parent']) != 'undefined')
                  {
                      var followPath = files[i]['parent'].substr(1).split('/').join(' <i class="fa fa-angle-right"></i> ');
                      $("#path").html("<strong>Current Location: </strong>" + followPath + "<br/><br/>");
                      $("#path").attr('data-path', files[i]['parent']);
                      $("#path2").val(files[i]['parent']);

                      if(files[i]['name'] != client && files[i]['name'] != '')
                      {
                          var parent = files[i]['parent'].substr(1).split('/');
                          var parentPos = files[i]['parent'].replace(files[i]['name'], '').replace('/' + client + '/', '');

                          str+= "<a href='#' onclick='getFileList(\""+ parentPos +"\");' class='list-group-item'><h4 class='list-group-item-heading'><i class='fa fa-folder-open'></i> " + parent[parent.length - 2] + "</h4><p></p></a>";
                      }
                      else
                      {
                          if(files.length == 1)
                              str = "<i>No Files</i>";
                      }
                  }
                  else
                  {
                      if(files[i]['is_file'] == 'true')
                      {

                          str+="<a href='#' class='list-group-item'><h4 class='list-group-item-heading'><i class='fa fa-file'></i> " + files[i]['name'] + "</h4><p>" + files[i]['modified'] + "</p></a>";
                      }
                      else
                      {
                          var path = files[i]['path'].replace('/' + client + '/', '');
                          str+="<a href='#' onclick='getFileList(\"" + path + "\");' class='list-group-item'><h4 class='list-group-item-heading'><i class='fa fa-folder'></i> " + files[i]['name'] + "</h4><p>" + files[i]['modified'] + "</p></a>";
                      }
                  }
              }
              $("#scrollWrapper div").html(str);
          },
          error: function(err){
              alert(err.statusText + ' - ' + err.responseText);
          }
      });
  }

PHP:

 <?php
//FileHandler.php
function getFileListing($dir, $folder)
{
    $pydio = new Pydio($folder);
    return json_encode($pydio->listd($dir));
}
?>

HTML:

<!DOCTYPE html>
<html>
<head>
      <meta charset="UTF-8" />
      <meta name="viewport" content="width=device-width, initial-scale=1.0">

      <title>Pydio Test</title>

      <!-- bootstrap -->
      <link href="css/bootstrap/bootstrap.css" rel="stylesheet" />

      <!-- libraries -->
      <link href="css/libs/font-awesome.css" type="text/css" rel="stylesheet" />

      <!-- global styles -->
      <link rel="stylesheet" type="text/css" href="css/abp/template.css">

      <!-- this page specific styles -->

      <!-- google font libraries -->
      <link href='http://fonts.googleapis.com/css?family=Open+Sans:400,600,700,300|Titillium+Web:200,300,400' rel='stylesheet' type='text/css'>
  </head>
  <body>
      <div class="container">
          <div class="row">
            <div class="col-md-12 col-sm-12">
                <div class="row">
                    <div class="col-md-8 col-sm-12>
                        <div id="path">
                        </div>
                        <div id="scrollWrapper">
                            <div class="list-group">
                            </div>
                        </div>
                    </div>
               </div>
             </div>
          </div>
       </div>
    </body>
   </html>

Vanessa Coote

I'm a programmer and former lecturer with years experience working with PHP, ColdFusion, Java, Visual Basic, JavaScript, HTML, and CSS.