phpZenfolio 1.2 - PHP Wrapper for the Zenfolio API ================================================== Written by Colin Seymour Project Homepage: http://phpzenfolio.com/ phpZenfolio is a PHP wrapper class for the Zenfolio API and is based on work I have done in phpSmug (http://phpsmug.com). Released under GNU General Public License version 3 (http://www.gnu.org/licenses/gpl.html) Copyright (C) 2010 Colin Seymour This file is part of phpZenfolio. phpZenfolio is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. phpZenfolio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with phpZenfolio. If not, see . For more information about the class and upcoming tools and applications using phpZenfolio, visit `http://phpzenfolio.com/'. Please help support the maintenance and development of phpZenfolio by making a donation (http://phpzenfolio.com/donate). Requirements ============ phpZenfolio is written in PHP and utilises functionality supplied with PHP 5.2 and later and optionally PEAR. From a PHP perspective, the only requirement is PHP 5.2 compiled with GD and optionally, curl support enabled. If you wish to use a database for caching, you will also need the following PEAR packages: * MDB2 2.5.0b3 (http://pear.php.net/package/MDB2) or later. * The corresponding MDB2_Driver_* (http://pear.php.net/search.php?q=MDB2_Driver&in=packages&setPerPage=20) for the database you wish to use. Please consult the above links for details on installing the PEAR modules. Installation ============ Copy the files from the installation package into a folder on your server. They need to be readable by your web server. You can put them into an include folder defined in your `php.ini' file, if you like, though it's not required. Usage ===== In order to use phpZenfolio, you will need to instantiate a new instance of the phpZenfolio object and then call the methods you need. phpZenfolio implements all methods and arguments as documented in the Zenfolio API. Accordingly, when calling a Zenfolio method, you will need to ensure that you pass the parameters exactly as they are documented in the Zenfolio API documentation (http://http://www.zenfolio.com/zf/help/api). Remember: *ALL* function names and arguments *ARE* case sensitive and the order is important. To make things easy for developers, phpZenfolio also provides several of it's own methods. These methods are: `login()', `enableCache()', `clearCache()', `upload()', `setProxy()', `imageUrl()' and `setAdapter()'. All phpZenfolio methods, and its constructor, take their arguments either as an associative array or as a list of `param=value' strings, unless otherwise documented. These methods are documented in more detail later in this document. To use phpZenfolio, all you have to do is include the file in your PHP scripts and create an instance. For example: require_once("phpZenfolio/phpZenfolio.php"); $f = new phpZenfolio(... arguments go here ...); The constructor takes two arguments, one obligatory and one optional: * `AppName' - Required This is the name, version and URL of the application you have built using phpZenfolio. There is no required format, but something like: "My Cool App/1.0 (http://my.url.com)" ... would be very useful and will allow Zenfolio to identify your application in the event of a problem. * `APIVer' - Optional Default: 1.6 Use this to set the endpoint you wish to use. The default is 1.6 as this is the latest endpoint provided by Zenfolio. As the constructor is a phpZenfolio specific method, it can be instantiated using one of the following methods: Arguments as strings: $f = new phpZenfolio("AppName=My Cool App/1.0 (http://app.com)", "APIVer=1.6"); Arguments as an associative array: $f = new phpZenfolio( array( "AppName" => "My Cool App/1.0 (http://app.com)", "APIVer" => "1.6") ); Naturally, you can predefine the array before instantiating the object and just pass the array variable. With the instance instantiated, you can now interact with the Zenfolio API using Zenfolio's native methods exactly as they're documented. Arguments to all Zenfolio native methods must be provided in the order they are documented in the API documentation. For example, use the following to get all recent sets that are of the PhotoSetType 'Gallery': $f->GetRecentSets('Gallery', 0, 3); Note the method's capitalisation and the arguments, these are as they are documented in the GetRecentSets() (http://www.zenfolio.com/zf/help/api/ref/methods/getrecentsets) method documentation. Some of the Zenfolio API methods, like `CreatePhotoSet()', require an object to be passed as one of the arguments. The object can be passed either as an associative array: $photoSetUpdater = array( "Title" => "PhotoSet Title", "Caption" => "PhotoSet Caption via API", "Keywords" => array("Keyword1", "keyword2"), "Categories" => array(), "CustomReference" => "testing/test-photoset" ); $f->CreatePhotoSet(12345, 'Gallery', $photoSetUpdater ); ... or as a standard class object: $photoSetUpdater = new stdClass(); $photoSetUpdater->Title = "PhotoSet Title"; $photoSetUpdater->Caption = "PhotoSet Caption via Object"|; $photoSetUpdater->Keywords = array("Keyword1", "keyword2"); $photoSetUpdater->Categories = array(); $photoSetUpdater->CustomReference = "testing/test-photoset"; $f->CreatePhotoSet(12345, 'Gallery', $photoSetUpdater ); All data returned by the method call is returned as the API documents it with the exception being objects are actually returned as arrays by phpZenfolio. In the event of an error, phpZenfolio will throw one of two exceptions: PhpZenfolioException in the event of a problem detected by phpZenfolio or HttpRequestException in the event of a problem detected by the code used to communicate with the API. Your application will need to catch these exceptions. Authentication ============== Many of the Zenfolio API methods are open to all users, whether they have Zenfolio accounts or not, however anything private or related to modification requires authentication. The Zenfolio API provides two methods of authentication (http://www.zenfolio.com/zf/help/api/guide/auth): Plain-Text and Challenge-Response. Both are equally good with the slightly more secure method being the Challenge-Response method as your password never travels across the wire. phpZenfolio allows you to use the API methods as documented, however to make things easy, a single `login()' method exists to allow you to authentication using either of these authentication methods: Challenge-Response (default): $f->login("Username=", "Password="); Plain-Text: $f->login("Username=", "Password=", "Plaintext=TRUE"); The Plain-Text method uses HTTPS/SSL for the authentication step to ensure your username and password are encrypted when transmitted to Zenfolio. Caching ======= Caching can be very important to a project as it can drastically improve the performance of your application. phpZenfolio has caching functionality that can cache data to a database or files, you just need to enable it. It is recommended that caching is enabled immediately after a new phpZenfolio instance is created, and before any other phpZenfolio methods are called. To enable caching, use the `enableCache()' function. The `enableCache()' method takes 4 arguments: * `type' - Required This is "db" for database or "fs" for filesystem. * `dsn' - Required for type=db This a PEAR::MDB2 DSN connection string, for example: mysql://user:password@server/database phpZenfolio uses the MDB2 PEAR module to interact with the database if you use database based caching. phpZenfolio does *NOT* supply the necessary PEAR modules. If you with to use a database for caching, you will need to download and install PEAR, the MDB2 PEAR module and the corresponding database driver yourself. See MDB2 Manual (http://pear.php.net/manual/en/package.database.mdb2.intro.php) for details. * `cache_dir' - Required for type=fs This is the folder/directory that the web server has write access to. This directory must already exist. Use absolute paths for best results as relative paths may have unexpected behaviour. They'll usually work, you'll just want to test them. You may not want to allow the world to view the files that are created during caching. If you want to hide this information, either make sure that your permissions are set correctly, or prevent the webserver from displaying *.cache files. In Apache, you can specify this in the configuration files or in a .htaccess file with the following directives: Deny from all Alternatively, you can specify a directory that is outside of the web server's document root. * `cache_expire' - Optional Default: 3600 This is the maximum age of each cache entry in seconds. * `table' - Optional Default: phpzenfolio_cache This is the database table name that will be used for storing the cached data. This is only applicable for database (db) caching and will be ignored if included for filesystem (fs) caching. If the table does not exist, phpZenfolio will attempt to create it. Each of the caching methods can be enabled as follows: Filesystem based cache: $f->enableCache("type=fs", "cache_dir=/tmp", "cache_expire=86400" ); Database based cache: $f->enableCache("type=db", "dsn=mysql://USERNAME:PASSWORD_database", "cache_expire=86400"); If you have caching enabled, and you make changes, it's a good idea to call `clearCache()' to refresh the cache so your changes are reflected immediately. Uploading ========= Uploading is very easy. You can either upload an image from your local system using the phpZenfolio supplied `upload()' method, or from a location on the web using the API's `CreatePhotoFromUrl()' method. * Upload Local File: To upload from your local filesystem using the phpZenfolio `upload()' method, you will need to have logged into Zenfolio via the API and have the `PhotoSetId' or it's `UploadUrl' as returned by the API. Then it's just a matter of calling the method with the various optional parameters. Upload using the PhotoSetId: $f->upload("PhotoSetId=123456", "File=/path/to/image.jpg"); Upload using the UploadUrl: $f->upload("UploadUrl=http://up.zenfolio.com/....", "File=/path/to/image.jpg"); At this time, the only supported options you can pass at the time of uploading are a "filename" the "modified" parameter which takes a RFC2822 formatted date string... $f->upload("PhotoSetId=123456", "File=/path/to/image.jpg", "filename=newfilename.jpg", "modified=Thu, 14 Jan 2010 13:08:07 +0200"); If you don't specify a filename, the original filename is used. * Upload from the web: Uploading to Zenfolio using a URL is done purely by the Zenfolio `CreatePhotoFromUrl()' API method: $f->CreatePhotoFromUrl( 12344, "http://www.example.com/images/image.jpg", null ); You can find full details on the options this method accepts in the CreatePhotoFromUrl (http://www.zenfolio.com/zf/help/api/ref/methods/createphotofromurl) method documentation. Unfortunately, there is no way to pass things like the photo title etc at the time of upload. You will need to set these later using the `UpdatePhoto()' method. Replacing Photos ================ In order to replace a photo, you will need to upload a new photo and then replace the old photo with the new using the Zenfolio ReplacePhoto() (http://www.zenfolio.com/zf/help/api/ref/methods/replacephoto) API method. Other Notes =========== * By default, phpZenfolio will attempt to use Curl to communicate with the Zenfolio API endpoint if it's available. If not, it'll revert to using sockets based communication using `fsockopen()'. If you wish to force the use of sockets, you can do so using the phpZenfolio supplied `setAdapter()' right after instantiating your instance: $f = new phpZenfolio("AppName="); $f->setAdapter("socket"); Valid arguments are "curl" (default) and "socket". * phpZenfolio implements Zenfolio objects (http://www.zenfolio.com/zf/help/api/ref/objects) as arrays. This makes implementation and usage easier. * Some people will need to use phpZenfolio from behind a proxy server. You can use the `setProxy()' method to set the appropriate proxy settings. For example: $f = new phpZenfolio("AppName="); $f->setProxy("server=", "port="); All your calls will then pass through the specified proxy on the specified port. If your proxy server requires a username and password, then add those options to the `setProxy()' method arguments too. For example: $f = new phpZenfolio("AppName="); $f->setProxy("server=", "port=", "user=", "password="); Note: Proxy support is currently only available when using the default "curl" adapter. * To make it easy to obtain the direct URL to an image, phpZenfolio supplies a `imageURL()' method that takes the Photo object as returned by methods like `LoadPhoto()' and `LoadPhotoSetPhotos()' and an integer for the desired photo size where the integer is one of those documented at `http://www.zenfolio.com/zf/help/api/guide/download'. For example: $f = new phpZenfolio("AppName="); $photos = $f->LoadPhotoSetPhotos(, , ); foreach ($photos as $photo) { echo ''; } * If phpZenfolio encounters an error, or Zenfolio returns a "failure" response, an exception will be thrown and your application will stop executing. If there is a problem with communicating with the endpoint, a HttpRequestException will be thrown. If an error is detected elsewhere, a PhpZenfolioException will be thrown. It is recommended that you configure your application to catch exceptions from phpZenfolio. Examples ======== phpZenfolio comes with 3 examples to help get you on your way. * `example-popular.php' illustrates how to obtain the 100 most popular galleries and display their title image linking to each individual gallery. * `example-login.php' illustrates how to login and display the images in your first photoset or collection. * `example-user.php' illustrates how to display the first 100 public photos of the user's the first public photoset found. You can see these examples in action at `http://phpzenfolio.com/examples'. And that's all folks. Keep up to date on developments and enhancements to phpZenfolio at `http://phpzenfolio.com/'. If you encounter any problems with phpZenfolio, please check the list of known issues with phpZenfolio and the API itself at `http://phpzenfolio.com/bugs'. If your issue is not there, please leave a comment on the revision page at `http://phpzenfolio.com/phpzenfolio-1.0'. If you are using phpZenfolio and wish to let the world know, drop me a line via the contact form at `http://phpzenfolio.com/about' and I'll add a link and brief description to the sidebar on `http://phpzenfolio.com/'. If you use and find phpZenfolio useful, please help support its maintenance and development by making a donation (http://phpzenfolio.com/donate). This document is also available online at `http://phpzenfolio.com/docs'. Change History ============== * 1.2 - 10 June '12 * Changed API endpoint to use api.zenfolio.com as requested by Zenfolio * Changed default API version to 1.6 * Added ability to perform ALL API requests over HTTPS (Ticket #4) * 1.1 - 28 Mar '11 * Use md5 to generate a uniq ID for each request instead of using intval() to ensure correct and consistent behaviour on 32-bit and 64-bit platforms. (Ticket #1) * Removed erroneous re-instantiation of processor when setting adapter. * Corrected check for safe_dir OR open_basedir so fails over to socket connection correctly (Ticket #2) * Cache only successful requests * Improved connection settings * 1.0 - 01 Oct '10 * Initial release.