diff --git a/android/.gitattributes b/android/.gitattributes new file mode 100644 index 0000000..412eeda --- /dev/null +++ b/android/.gitattributes @@ -0,0 +1,22 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Custom for Visual Studio +*.cs diff=csharp +*.sln merge=union +*.csproj merge=union +*.vbproj merge=union +*.fsproj merge=union +*.dbproj merge=union + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/android/.gitignore b/android/.gitignore new file mode 100644 index 0000000..b9d6bd9 --- /dev/null +++ b/android/.gitignore @@ -0,0 +1,215 @@ +################# +## Eclipse +################# + +*.pydevproject +.project +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.classpath +.settings/ +.loadpath + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# CDT-specific +.cproject + +# PDT-specific +.buildpath + + +################# +## Visual Studio +################# + +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results + +[Dd]ebug/ +[Rr]elease/ +x64/ +build/ +[Bb]in/ +[Oo]bj/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +*_i.c +*_p.c +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.log +*.scc + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +*.ncrunch* +.*crunch*.local.xml + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.Publish.xml +*.pubxml + +# NuGet Packages Directory +## TODO: If you have NuGet Package Restore enabled, uncomment the next line +#packages/ + +# Windows Azure Build Output +csx +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.[Pp]ublish.xml +*.pfx +*.publishsettings + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +App_Data/*.mdf +App_Data/*.ldf + +############# +## Windows detritus +############# + +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Mac crap +.DS_Store + + +############# +## Python +############# + +*.py[co] + +# Packages +*.egg +*.egg-info +dist/ +build/ +eggs/ +parts/ +var/ +sdist/ +develop-eggs/ +.installed.cfg + +# Installer logs +pip-log.txt + +# Unit test / coverage reports +.coverage +.tox + +#Translations +*.mo + +#Mr Developer +.mr.developer.cfg diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml new file mode 100644 index 0000000..722e59f --- /dev/null +++ b/android/AndroidManifest.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/android/README b/android/README new file mode 100644 index 0000000..5ec5168 --- /dev/null +++ b/android/README @@ -0,0 +1,11 @@ +ImageHostingService Android Application + +Installation: +1. Import Android Application Project +2. setup android SDK build target in AndroidManifest.xml +3. run and enjoy + +see builded APK file in built/ directory + +P.S: +application UI is very simple, pay attention on code structure. \ No newline at end of file diff --git a/android/built/ImageHostingService.apk b/android/built/ImageHostingService.apk new file mode 100644 index 0000000..cc32313 Binary files /dev/null and b/android/built/ImageHostingService.apk differ diff --git a/android/gen/tj/zar/projects/imagehostingservice/BuildConfig.java b/android/gen/tj/zar/projects/imagehostingservice/BuildConfig.java new file mode 100644 index 0000000..cb0750b --- /dev/null +++ b/android/gen/tj/zar/projects/imagehostingservice/BuildConfig.java @@ -0,0 +1,6 @@ +/** Automatically generated file. DO NOT MODIFY */ +package tj.zar.projects.imagehostingservice; + +public final class BuildConfig { + public final static boolean DEBUG = true; +} \ No newline at end of file diff --git a/android/gen/tj/zar/projects/imagehostingservice/R.java b/android/gen/tj/zar/projects/imagehostingservice/R.java new file mode 100644 index 0000000..bb89e95 --- /dev/null +++ b/android/gen/tj/zar/projects/imagehostingservice/R.java @@ -0,0 +1,82 @@ +/* AUTO-GENERATED FILE. DO NOT MODIFY. + * + * This class was automatically generated by the + * aapt tool from the resource data it found. It + * should not be modified by hand. + */ + +package tj.zar.projects.imagehostingservice; + +public final class R { + public static final class attr { + } + public static final class drawable { + public static final int ic_launcher=0x7f020000; + } + public static final class id { + public static final int addDescriptionButton=0x7f060007; + public static final int addFavoriteButton=0x7f060009; + public static final int descriptionText=0x7f060004; + public static final int favoriteImagesGrid=0x7f060005; + public static final int generateFlikrButton=0x7f060001; + public static final int generateInstagramButton=0x7f060002; + public static final int generatePanel=0x7f060000; + public static final int image=0x7f060003; + public static final int randomImagesGrid=0x7f060008; + public static final int removeFavoriteButton=0x7f060006; + } + public static final class layout { + public static final int activity_home=0x7f030000; + public static final int adapter_favorite_image=0x7f030001; + public static final int adapter_random_image=0x7f030002; + public static final int component_favorite_gallery=0x7f030003; + public static final int component_random_gallery=0x7f030004; + public static final int dialog_add_description=0x7f030005; + } + public static final class string { + public static final int add_description=0x7f040002; + public static final int add_image_description=0x7f040003; + public static final int app_name=0x7f040000; + public static final int description_has_been_added=0x7f04000a; + public static final int favorite_images=0x7f040004; + public static final int generate_from_flikr=0x7f040008; + public static final int generate_from_instagram=0x7f040009; + public static final int image_has_been_removed_from_favorite_list=0x7f04000b; + public static final int image_set_as_a_favorite=0x7f04000e; + public static final int menu_settings=0x7f040001; + public static final int no_images_to_add_description=0x7f04000d; + public static final int no_images_to_remove=0x7f04000c; + public static final int nothing_to_set_as_favorite=0x7f04000f; + public static final int random_images=0x7f040006; + public static final int remove=0x7f040005; + public static final int set_favorite=0x7f040007; + } + public static final class style { + /** + Base application theme, dependent on API level. This theme is replaced + by AppBaseTheme from res/values-vXX/styles.xml on newer devices. + + + Theme customizations available in newer API levels can go in + res/values-vXX/styles.xml, while customizations related to + backward-compatibility can go here. + + + Base application theme for API 11+. This theme completely replaces + AppBaseTheme from res/values/styles.xml on API 11+ devices. + + API 11 theme customizations can go here. + + Base application theme for API 14+. This theme completely replaces + AppBaseTheme from BOTH res/values/styles.xml and + res/values-v11/styles.xml on API 14+ devices. + + API 14 theme customizations can go here. + */ + public static final int AppBaseTheme=0x7f050000; + /** Application theme. + All customizations that are NOT specific to a particular API-level can go here. + */ + public static final int AppTheme=0x7f050001; + } +} diff --git a/android/ic_launcher-web.png b/android/ic_launcher-web.png new file mode 100644 index 0000000..489f550 Binary files /dev/null and b/android/ic_launcher-web.png differ diff --git a/android/libs/android-support-v4.jar b/android/libs/android-support-v4.jar new file mode 100644 index 0000000..6080877 Binary files /dev/null and b/android/libs/android-support-v4.jar differ diff --git a/android/libs/zarlib.jar b/android/libs/zarlib.jar new file mode 100644 index 0000000..e1b3dda Binary files /dev/null and b/android/libs/zarlib.jar differ diff --git a/android/proguard-project.txt b/android/proguard-project.txt new file mode 100644 index 0000000..f2fe155 --- /dev/null +++ b/android/proguard-project.txt @@ -0,0 +1,20 @@ +# To enable ProGuard in your project, edit project.properties +# to define the proguard.config property as described in that file. +# +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in ${sdk.dir}/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the ProGuard +# include property in project.properties. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} diff --git a/android/project.properties b/android/project.properties new file mode 100644 index 0000000..9b84a6b --- /dev/null +++ b/android/project.properties @@ -0,0 +1,14 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system edit +# "ant.properties", and override values to adapt the script to your +# project structure. +# +# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): +#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt + +# Project target. +target=android-16 diff --git a/android/res/drawable-hdpi/ic_launcher.png b/android/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 0000000..5a91e7a Binary files /dev/null and b/android/res/drawable-hdpi/ic_launcher.png differ diff --git a/android/res/drawable-ldpi/ic_launcher.png b/android/res/drawable-ldpi/ic_launcher.png new file mode 100644 index 0000000..233c123 Binary files /dev/null and b/android/res/drawable-ldpi/ic_launcher.png differ diff --git a/android/res/drawable-mdpi/ic_launcher.png b/android/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 0000000..aec9c14 Binary files /dev/null and b/android/res/drawable-mdpi/ic_launcher.png differ diff --git a/android/res/drawable-xhdpi/ic_launcher.png b/android/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 0000000..6fdefd6 Binary files /dev/null and b/android/res/drawable-xhdpi/ic_launcher.png differ diff --git a/android/res/layout-land/activity_home.xml b/android/res/layout-land/activity_home.xml new file mode 100644 index 0000000..00abbb8 --- /dev/null +++ b/android/res/layout-land/activity_home.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+

+ Description will appear on the hover of the image +

+
+
+
+ +
+
+
+ + + + + + + \ No newline at end of file diff --git a/web/lib/flikr_api/README.txt b/web/lib/flikr_api/README.txt new file mode 100644 index 0000000..8524ed1 --- /dev/null +++ b/web/lib/flikr_api/README.txt @@ -0,0 +1,215 @@ +phpFlickr Class 3.0 +Written by Dan Coulter (dancoulter@users.sourceforge.net) +Project Homepage: http://www.phpflickr.com/ +Google Code Project Page: http://code.google.com/p/phpflickr/ +Released under GNU Lesser General Public License (http://www.gnu.org/copyleft/lgpl.html) +For more information about the class and upcoming tools and applications using it, +visit http://www.phpflickr.com/ or http://code.google.com/p/phpflickr/ + +If you are interested in hiring me for a project (involving phpFlickr +or not), feel free to email me. + +Installation instructions: +1. Copy the files from the installation package into a folder on your + server. They need to be readible 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. + +2. All you have to do now is include the file in your PHP scripts and + create an instance. For example: + $f = new phpFlickr(); + + The constructor has three arguments: + A. $api_key - This is the API key given to you by flickr.com. This + argument is required and you can get an API Key at: + http://www.flickr.com/services/api/key.gne + + B. $secret - The "secret" is optional because is not required to + make unauthenticated calls, but is absolutely required for the + new authentication API (see Authentication section below). You + will get one assigned alongside your api key. + + C. $die_on_error - This takes a boolean value and determines + whether the class will die (aka cease operation) if the API + returns an error statement. It defaults to false. Every method + will return false if the API returns an error. You can access + error messages using the getErrorCode() and getErrorMsg() + methods. + +3. All of the API methods have been implemented in my class. You can + see a full list and documentation here: + http://www.flickr.com/services/api/ + To call a method, remove the "flickr." part of the name and replace + any periods with underscores. For example, instead of + flickr.photos.search, you would call $f->photos_search() or instead + of flickr.photos.licenses.getInfo, you would call + $f->photos_licenses_getInfo() (yes, it is case sensitive). + + All functions have their arguments implemented in the list order on + their documentation page (a link to which is included with each + method in the phpFlickr clasS). The only exceptions to this are + photos_search(), photos_getWithoutGeodata() and + photos_getWithoutGeodata() which have so many optional arguments + that it's easier for everyone if you just have to pass an + associative array of arguments. See the comment in the + photos_search() definition in phpFlickr.php for more information. + + + +Authentication: + As of this release of the phpFlickr class there is only one authentication method + available to the API. This method is somewhat complex, but is far more secure and + allows your users to feel a little safer authenticating to your application. You'll + no longer have to ask for their username and password. + + Authentication API - http://www.flickr.com/services/api/auth.spec.html + + I know how complicated this API looks at first glance, so I've tried to + make this as transparent to the coding process. I'll go through the steps + you'll need to use this. Both the auth.php and getToken.php file will + need your API Key and Secret entered before you can use them. + + To have end users authenticate their accounts: + First, setup a callback script. I've included a callback script that + is pretty flexible. You'll find it in the package entitled "auth.php". + You'll need to go to flickr and point your api key to this file as the + callback script. Once you've done this, on any page that you want to + require the end user end user to authenticate their flickr account to + your app, just call the phpFlickr::auth() function with whatever + permission you need to use. + For example: + $f->auth("write"); + The three permissions are "read", "write" and "delete". The function + defaults to "read", if you leave it blank. + + Calling this function will send the user's browser to Flickr's page to + authenticate to your app. Once they have logged in, it will bounce + them back to your callback script which will redirect back to the + original page that you called the auth() function from after setting + a session variable to save their authentication token. If that session + variable exists, calling the auth() function will return the permissions + that the user granted your app on the Flickr page instead of redirecting + to an external page. + + To authenticate the app to your account to show your private pictures (for example) + This method will allow you to have the app authenticate to one specific + account, no matter who views your website. This is useful to display + private photos or photosets (among other things). + + *Note*: The method below is a little hard to understand, so I've setup a tool + to help you through this: http://www.phpflickr.com/tools/auth/. + + First, you'll have to setup a callback script with Flickr. Once you've + done that, edit line 12 of the included getToken.php file to reflect + which permissions you'll need for the app. Then browse to the page. + Once you've authorized the app with Flickr, it'll send you back to that + page which will give you a token which will look something like this: + 1234-567890abcdef1234 + Go to the file where you are creating an instance of phpFlickr (I suggest + an include file) and after you've created it set the token to use: + $f->setToken(""); + This token never expires, so you don't have to worry about having to + login periodically. + + +Using Caching: + Caching can be very important to a project. Just a few calls to the Flickr API + can take long enough to bore your average web user (depending on the calls you + are making). I've built in caching that will access either a database or files + in your filesystem. To enable caching, use the phpFlickr::enableCache() function. + This function requires at least two arguments. The first will be the type of + cache you're using (either "db" or "fs") + + 1. If you're using database caching, you'll need to supply a PEAR::DB connection + string. For example: + $flickr->enableCache("db", "mysql://user:password@server/database"); + The third (optional) argument is expiration of the cache in seconds (defaults + to 600). The fourth (optional) argument is the table where you want to store + the cache. This defaults to flickr_cache and will attempt to create the table + if it does not already exist. + + 2. If you're using filesystem caching, you'll need to supply a folder where the + web server has write access. For example: + $flickr->enableCache("fs", "/var/www/phpFlickrCache"); + The third (optional) argument is, the same as in the Database caching, an + expiration in seconds for the cache. + Note: filesystem caching will probably be slower than database caching. I + haven't done any tests of this, but if you get large amounts of calls, the + process of cleaning out old calls may get hard on your server. + + 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 disable 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. + +Uploading + Uploading is pretty simple. Aside from being authenticated (see Authentication + section) the very minimum that you'll have to pass is a path to an image file on + your php server. You can do either synchronous or asynchronous uploading as follows: + synchronous: sync_upload("photo.jpg"); + asynchronous: async_upload("photo.jpg"); + + The basic difference is that synchronous uploading waits around until Flickr + processes the photo and returns a PhotoID. Asynchronous just uploads the + picture and gets a "ticketid" that you can use to check on the status of your + upload. Asynchronous is much faster, though the photoid won't be instantly + available for you. You can read more about asynchronous uploading here: + http://www.flickr.com/services/api/upload.async.html + + Both of the functions take the same arguments which are: + Photo: The path of the file to upload. + Title: The title of the photo. + Description: A description of the photo. May contain some limited HTML. + Tags: A space-separated list of tags to apply to the photo. + is_public: Set to 0 for no, 1 for yes. + is_friend: Set to 0 for no, 1 for yes. + is_family: Set to 0 for no, 1 for yes. + +Replacing Photos + Flickr has released API support for uploading a replacement photo. To use this + new method, just use the "replace" function in phpFlickr. You'll be required + to pass the file name and Flickr's photo ID. You need to authenticate your script + with "write" permissions before you can replace a photo. The arguments are: + Photo: The path of the file to upload. + Photo ID: The numeric Flickr ID of the photo you want to replace. + Async (optional): Set to 0 for a synchronous call, 1 for asynchronous. + If you use the asynchronous call, it will return a ticketid instead + of photoid. + +Other Notes: + 1. Many of the methods have optional arguments. For these, I have implemented + them in the same order that the Flickr API documentation lists them. PHP + allows for optional arguments in function calls, but if you want to use the + third optional argument, you have to fill in the others to the left first. + You can use the "NULL" value (without quotes) in the place of an actual + argument. For example: + $f->groups_pools_getPhotos($group_id, NULL, NULL, 10); + This will get the first ten photos from a specific group's pool. If you look + at the documentation, you will see that there is another argument, "page". I've + left it off because it appears after "per_page". + 2. Some people will need to ues phpFlickr from behind a proxy server. I've + implemented a method that will allow you to use an HTTP proxy for all of your + traffic. Let's say that you have a proxy server on your local server running + at port 8181. This is the code you would use: + $f = new phpFlickr("[api key]"); + $f->setProxy("localhost", "8181"); + After that, all of your calls will be automatically made through your proxy server. + + +That's it! Enjoy the class. Check out the project page (listed above) for updates +and news. I plan to implement file uploads and functions to aggregate data from +several different methods for easier use in a web application. Thanks for your +interest in this project! + + Please email me if you have any questions or problems. You'll find my email + at the top of this file. + + diff --git a/web/lib/flikr_api/auth.php b/web/lib/flikr_api/auth.php new file mode 100644 index 0000000..0cee4dc --- /dev/null +++ b/web/lib/flikr_api/auth.php @@ -0,0 +1,38 @@ +auth($permissions, false); + } else { + $f->auth_getToken($_GET['frob']); + } + + if (empty($redirect)) { + header("Location: " . $default_redirect); + } else { + header("Location: " . $redirect); + } + +?> \ No newline at end of file diff --git a/web/lib/flikr_api/example.php b/web/lib/flikr_api/example.php new file mode 100644 index 0000000..8b409b4 --- /dev/null +++ b/web/lib/flikr_api/example.php @@ -0,0 +1,30 @@ +" with one provided + * by Flickr: http://www.flickr.com/services/api/key.gne + */ + +require_once("phpFlickr.php"); +$f = new phpFlickr(""); + +$recent = $f->photos_getRecent(); + +foreach ($recent['photo'] as $photo) { + $owner = $f->people_getInfo($photo['owner']); + echo ""; + echo $photo['title']; + echo " Owner: "; + echo ""; + echo $owner['username']; + echo "
"; +} +?> diff --git a/web/lib/flikr_api/getToken.php b/web/lib/flikr_api/getToken.php new file mode 100644 index 0000000..1d232e4 --- /dev/null +++ b/web/lib/flikr_api/getToken.php @@ -0,0 +1,19 @@ +", ""); + + //change this to the permissions you will need + $f->auth("read"); + + echo "Copy this token into your code: " . $_SESSION['phpFlickr_auth_token']; + +?> \ No newline at end of file diff --git a/web/lib/flikr_api/phpFlickr.php b/web/lib/flikr_api/phpFlickr.php new file mode 100644 index 0000000..df9d7d7 --- /dev/null +++ b/web/lib/flikr_api/phpFlickr.php @@ -0,0 +1,1805 @@ +api_key = $api_key; + $this->secret = $secret; + $this->die_on_error = $die_on_error; + $this->service = "flickr"; + + //Find the PHP version and store it for future reference + $this->php_version = explode("-", phpversion()); + $this->php_version = explode(".", $this->php_version[0]); + } + + function enableCache ($type, $connection, $cache_expire = 600, $table = 'flickr_cache') { + // Turns on caching. $type must be either "db" (for database caching) or "fs" (for filesystem). + // When using db, $connection must be a PEAR::DB connection string. Example: + // "mysql://user:password@server/database" + // If the $table, doesn't exist, it will attempt to create it. + // When using file system, caching, the $connection is the folder that the web server has write + // access to. Use absolute paths for best results. Relative paths may have unexpected behavior + // when you include this. They'll usually work, you'll just want to test them. + if ($type == 'db') { + if ( preg_match('|mysql://([^:]*):([^@]*)@([^/]*)/(.*)|', $connection, $matches) ) { + //Array ( [0] => mysql://user:password@server/database [1] => user [2] => password [3] => server [4] => database ) + $db = mysql_connect($matches[3], $matches[1], $matches[2]); + mysql_select_db($matches[4], $db); + + /* + * If high performance is crucial, you can easily comment + * out this query once you've created your database table. + */ + mysql_query(" + CREATE TABLE IF NOT EXISTS `$table` ( + `request` CHAR( 35 ) NOT NULL , + `response` MEDIUMTEXT NOT NULL , + `expiration` DATETIME NOT NULL , + INDEX ( `request` ) + ) TYPE = MYISAM + ", $db); + + $result = mysql_query("SELECT COUNT(*) FROM $table", $db); + $result = mysql_fetch_row($result); + if ( $result[0] > $this->max_cache_rows ) { + mysql_query("DELETE FROM $table WHERE expiration < DATE_SUB(NOW(), INTERVAL $cache_expire second)", $db); + mysql_query('OPTIMIZE TABLE ' . $this->cache_table, $db); + } + $this->cache = 'db'; + $this->cache_db = $db; + $this->cache_table = $table; + } + } elseif ($type == 'fs') { + $this->cache = 'fs'; + $connection = realpath($connection); + $this->cache_dir = $connection; + if ($dir = opendir($this->cache_dir)) { + while ($file = readdir($dir)) { + if (substr($file, -6) == '.cache' && ((filemtime($this->cache_dir . '/' . $file) + $cache_expire) < time()) ) { + unlink($this->cache_dir . '/' . $file); + } + } + } + } elseif ( $type == 'custom' ) { + $this->cache = "custom"; + $this->custom_cache_get = $connection[0]; + $this->custom_cache_set = $connection[1]; + } + $this->cache_expire = $cache_expire; + } + + function getCached ($request) + { + //Checks the database or filesystem for a cached result to the request. + //If there is no cache result, it returns a value of false. If it finds one, + //it returns the unparsed XML. + foreach ( $request as $key => $value ) { + if ( empty($value) ) unset($request[$key]); + else $request[$key] = (string) $request[$key]; + } + //if ( is_user_logged_in() ) print_r($request); + $reqhash = md5(serialize($request)); + $this->cache_key = $reqhash; + $this->cache_request = $request; + if ($this->cache == 'db') { + $result = mysql_query("SELECT response FROM " . $this->cache_table . " WHERE request = '" . $reqhash . "' AND DATE_SUB(NOW(), INTERVAL " . (int) $this->cache_expire . " SECOND) < expiration", $this->cache_db); + if ( mysql_num_rows($result) ) { + $result = mysql_fetch_assoc($result); + return $result['response']; + } else { + return false; + } + } elseif ($this->cache == 'fs') { + $file = $this->cache_dir . '/' . $reqhash . '.cache'; + if (file_exists($file)) { + if ($this->php_version[0] > 4 || ($this->php_version[0] == 4 && $this->php_version[1] >= 3)) { + return file_get_contents($file); + } else { + return implode('', file($file)); + } + } + } elseif ( $this->cache == 'custom' ) { + return call_user_func_array($this->custom_cache_get, array($reqhash)); + } + return false; + } + + function cache ($request, $response) + { + //Caches the unparsed response of a request. + unset($request['api_sig']); + foreach ( $request as $key => $value ) { + if ( empty($value) ) unset($request[$key]); + else $request[$key] = (string) $request[$key]; + } + $reqhash = md5(serialize($request)); + if ($this->cache == 'db') { + //$this->cache_db->query("DELETE FROM $this->cache_table WHERE request = '$reqhash'"); + $result = mysql_query("SELECT COUNT(*) FROM " . $this->cache_table . " WHERE request = '" . $reqhash . "'", $this->cache_db); + $result = mysql_fetch_row($result); + if ( $result[0] ) { + $sql = "UPDATE " . $this->cache_table . " SET response = '" . str_replace("'", "''", $response) . "', expiration = '" . strftime("%Y-%m-%d %H:%M:%S") . "' WHERE request = '" . $reqhash . "'"; + mysql_query($sql, $this->cache_db); + } else { + $sql = "INSERT INTO " . $this->cache_table . " (request, response, expiration) VALUES ('$reqhash', '" . str_replace("'", "''", $response) . "', '" . strftime("%Y-%m-%d %H:%M:%S") . "')"; + mysql_query($sql, $this->cache_db); + } + } elseif ($this->cache == "fs") { + $file = $this->cache_dir . "/" . $reqhash . ".cache"; + $fstream = fopen($file, "w"); + $result = fwrite($fstream,$response); + fclose($fstream); + return $result; + } elseif ( $this->cache == "custom" ) { + return call_user_func_array($this->custom_cache_set, array($reqhash, $response, $this->cache_expire)); + } + return false; + } + + function setCustomPost ( $function ) { + $this->custom_post = $function; + } + + function post ($data, $type = null) { + if ( is_null($type) ) { + $url = $this->rest_endpoint; + } + + if ( !is_null($this->custom_post) ) { + return call_user_func($this->custom_post, $url, $data); + } + + if ( !preg_match("|http://(.*?)(/.*)|", $url, $matches) ) { + die('There was some problem figuring out your endpoint'); + } + + if ( function_exists('curl_init') ) { + // Has curl. Use it! + $curl = curl_init($this->rest_endpoint); + curl_setopt($curl, CURLOPT_POST, true); + curl_setopt($curl, CURLOPT_POSTFIELDS, $data); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + $response = curl_exec($curl); + curl_close($curl); + } else { + // Use sockets. + foreach ( $data as $key => $value ) { + $data[$key] = $key . '=' . urlencode($value); + } + $data = implode('&', $data); + + $fp = @pfsockopen($matches[1], 80); + if (!$fp) { + die('Could not connect to the web service'); + } + fputs ($fp,'POST ' . $matches[2] . " HTTP/1.1\n"); + fputs ($fp,'Host: ' . $matches[1] . "\n"); + fputs ($fp,"Content-type: application/x-www-form-urlencoded\n"); + fputs ($fp,"Content-length: ".strlen($data)."\n"); + fputs ($fp,"Connection: close\r\n\r\n"); + fputs ($fp,$data . "\n\n"); + $response = ""; + while(!feof($fp)) { + $response .= fgets($fp, 1024); + } + fclose ($fp); + $chunked = false; + $http_status = trim(substr($response, 0, strpos($response, "\n"))); + if ( $http_status != 'HTTP/1.1 200 OK' ) { + die('The web service endpoint returned a "' . $http_status . '" response'); + } + if ( strpos($response, 'Transfer-Encoding: chunked') !== false ) { + $temp = trim(strstr($response, "\r\n\r\n")); + $response = ''; + $length = trim(substr($temp, 0, strpos($temp, "\r"))); + while ( trim($temp) != "0" && ($length = trim(substr($temp, 0, strpos($temp, "\r")))) != "0" ) { + $response .= trim(substr($temp, strlen($length)+2, hexdec($length))); + $temp = trim(substr($temp, strlen($length) + 2 + hexdec($length))); + } + } elseif ( strpos($response, 'HTTP/1.1 200 OK') !== false ) { + $response = trim(strstr($response, "\r\n\r\n")); + } + } + return $response; + } + + function request ($command, $args = array(), $nocache = false) + { + //Sends a request to Flickr's REST endpoint via POST. + if (substr($command,0,7) != "flickr.") { + $command = "flickr." . $command; + } + + //Process arguments, including method and login data. + $args = array_merge(array("method" => $command, "format" => "php_serial", "api_key" => $this->api_key), $args); + if (!empty($this->token)) { + $args = array_merge($args, array("auth_token" => $this->token)); + } elseif (!empty($_SESSION['phpFlickr_auth_token'])) { + $args = array_merge($args, array("auth_token" => $_SESSION['phpFlickr_auth_token'])); + } + ksort($args); + $auth_sig = ""; + $this->last_request = $args; + if (!($this->response = $this->getCached($args)) || $nocache) { + foreach ($args as $key => $data) { + if ( is_null($data) ) { + unset($args[$key]); + continue; + } + $auth_sig .= $key . $data; + } + if (!empty($this->secret)) { + $api_sig = md5($this->secret . $auth_sig); + $args['api_sig'] = $api_sig; + } + $this->response = $this->post($args); + $this->cache($args, $this->response); + } + + /* + * Uncomment this line (and comment out the next one) if you're doing large queries + * and you're concerned about time. This will, however, change the structure of + * the result, so be sure that you look at the results. + */ + //$this->parsed_response = unserialize($this->response); + $this->parsed_response = $this->clean_text_nodes(unserialize($this->response)); + if ($this->parsed_response['stat'] == 'fail') { + if ($this->die_on_error) die("The Flickr API returned the following error: #{$this->parsed_response['code']} - {$this->parsed_response['message']}"); + else { + $this->error_code = $this->parsed_response['code']; + $this->error_msg = $this->parsed_response['message']; + $this->parsed_response = false; + } + } else { + $this->error_code = false; + $this->error_msg = false; + } + return $this->response; + } + + function clean_text_nodes ($arr) { + if (!is_array($arr)) { + return $arr; + } elseif (count($arr) == 0) { + return $arr; + } elseif (count($arr) == 1 && array_key_exists('_content', $arr)) { + return $arr['_content']; + } else { + foreach ($arr as $key => $element) { + $arr[$key] = $this->clean_text_nodes($element); + } + return($arr); + } + } + + function setToken ($token) { + // Sets an authentication token to use instead of the session variable + $this->token = $token; + } + + function setProxy ($server, $port) { + // Sets the proxy for all phpFlickr calls. + $this->req->setProxy($server, $port); + } + + function getErrorCode () { + // Returns the error code of the last call. If the last call did not + // return an error. This will return a false boolean. + return $this->error_code; + } + + function getErrorMsg () { + // Returns the error message of the last call. If the last call did not + // return an error. This will return a false boolean. + return $this->error_msg; + } + + /* These functions are front ends for the flickr calls */ + + function buildPhotoURL ($photo, $size = "Medium") { + //receives an array (can use the individual photo data returned + //from an API call) and returns a URL (doesn't mean that the + //file size exists) + $sizes = array( + "square" => "_s", + "large square" => "_q", + "thumbnail" => "_t", + "small" => "_m", + "medium" => "", + "medium_640" => "_z", + "large" => "_b", + "original" => "_o" + ); + + $size = strtolower($size); + if (!array_key_exists($size, $sizes)) { + $size = "medium"; + } + + if ($size == "original") { + $url = "http://farm" . $photo['farm'] . ".static.flickr.com/" . $photo['server'] . "/" . $photo['id'] . "_" . $photo['originalsecret'] . "_o" . "." . $photo['originalformat']; + } else { + $url = "http://farm" . $photo['farm'] . ".static.flickr.com/" . $photo['server'] . "/" . $photo['id'] . "_" . $photo['secret'] . $sizes[$size] . ".jpg"; + } + return $url; + } + + function getFriendlyGeodata ($lat, $lon) { + /* I've added this method to get the friendly geodata (i.e. 'in New York, NY') that the + * website provides, but isn't available in the API. I'm providing this service as long + * as it doesn't flood my server with requests and crash it all the time. + */ + return unserialize(file_get_contents('http://phpflickr.com/geodata/?format=php&lat=' . $lat . '&lon=' . $lon)); + } + + function sync_upload ($photo, $title = null, $description = null, $tags = null, $is_public = null, $is_friend = null, $is_family = null) { + if ( function_exists('curl_init') ) { + // Has curl. Use it! + + //Process arguments, including method and login data. + $args = array("api_key" => $this->api_key, "title" => $title, "description" => $description, "tags" => $tags, "is_public" => $is_public, "is_friend" => $is_friend, "is_family" => $is_family); + if (!empty($this->token)) { + $args = array_merge($args, array("auth_token" => $this->token)); + } elseif (!empty($_SESSION['phpFlickr_auth_token'])) { + $args = array_merge($args, array("auth_token" => $_SESSION['phpFlickr_auth_token'])); + } + + ksort($args); + $auth_sig = ""; + foreach ($args as $key => $data) { + if ( is_null($data) ) { + unset($args[$key]); + } else { + $auth_sig .= $key . $data; + } + } + if (!empty($this->secret)) { + $api_sig = md5($this->secret . $auth_sig); + $args["api_sig"] = $api_sig; + } + + $photo = realpath($photo); + $args['photo'] = '@' . $photo; + + + $curl = curl_init($this->upload_endpoint); + curl_setopt($curl, CURLOPT_POST, true); + curl_setopt($curl, CURLOPT_POSTFIELDS, $args); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + $response = curl_exec($curl); + $this->response = $response; + curl_close($curl); + + $rsp = explode("\n", $response); + foreach ($rsp as $line) { + if (preg_match('|die_on_error) + die("The Flickr API returned the following error: #{$match[1]} - {$match[2]}"); + else { + $this->error_code = $match[1]; + $this->error_msg = $match[2]; + $this->parsed_response = false; + return false; + } + } elseif (preg_match("|(.*)|", $line, $match)) { + $this->error_code = false; + $this->error_msg = false; + return $match[1]; + } + } + + } else { + die("Sorry, your server must support CURL in order to upload files"); + } + + } + + function async_upload ($photo, $title = null, $description = null, $tags = null, $is_public = null, $is_friend = null, $is_family = null) { + if ( function_exists('curl_init') ) { + // Has curl. Use it! + + //Process arguments, including method and login data. + $args = array("async" => 1, "api_key" => $this->api_key, "title" => $title, "description" => $description, "tags" => $tags, "is_public" => $is_public, "is_friend" => $is_friend, "is_family" => $is_family); + if (!empty($this->token)) { + $args = array_merge($args, array("auth_token" => $this->token)); + } elseif (!empty($_SESSION['phpFlickr_auth_token'])) { + $args = array_merge($args, array("auth_token" => $_SESSION['phpFlickr_auth_token'])); + } + + ksort($args); + $auth_sig = ""; + foreach ($args as $key => $data) { + if ( is_null($data) ) { + unset($args[$key]); + } else { + $auth_sig .= $key . $data; + } + } + if (!empty($this->secret)) { + $api_sig = md5($this->secret . $auth_sig); + $args["api_sig"] = $api_sig; + } + + $photo = realpath($photo); + $args['photo'] = '@' . $photo; + + + $curl = curl_init($this->upload_endpoint); + curl_setopt($curl, CURLOPT_POST, true); + curl_setopt($curl, CURLOPT_POSTFIELDS, $args); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + $response = curl_exec($curl); + $this->response = $response; + curl_close($curl); + + $rsp = explode("\n", $response); + foreach ($rsp as $line) { + if (ereg('die_on_error) + die("The Flickr API returned the following error: #{$match[1]} - {$match[2]}"); + else { + $this->error_code = $match[1]; + $this->error_msg = $match[2]; + $this->parsed_response = false; + return false; + } + } elseif (ereg("(.*)error_code = false; + $this->error_msg = false; + return $match[1]; + } + } + } else { + die("Sorry, your server must support CURL in order to upload files"); + } + } + + // Interface for new replace API method. + function replace ($photo, $photo_id, $async = null) { + if ( function_exists('curl_init') ) { + // Has curl. Use it! + + //Process arguments, including method and login data. + $args = array("api_key" => $this->api_key, "photo_id" => $photo_id, "async" => $async); + if (!empty($this->token)) { + $args = array_merge($args, array("auth_token" => $this->token)); + } elseif (!empty($_SESSION['phpFlickr_auth_token'])) { + $args = array_merge($args, array("auth_token" => $_SESSION['phpFlickr_auth_token'])); + } + + ksort($args); + $auth_sig = ""; + foreach ($args as $key => $data) { + if ( is_null($data) ) { + unset($args[$key]); + } else { + $auth_sig .= $key . $data; + } + } + if (!empty($this->secret)) { + $api_sig = md5($this->secret . $auth_sig); + $args["api_sig"] = $api_sig; + } + + $photo = realpath($photo); + $args['photo'] = '@' . $photo; + + + $curl = curl_init($this->replace_endpoint); + curl_setopt($curl, CURLOPT_POST, true); + curl_setopt($curl, CURLOPT_POSTFIELDS, $args); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + $response = curl_exec($curl); + $this->response = $response; + curl_close($curl); + + if ($async == 1) + $find = 'ticketid'; + else + $find = 'photoid'; + + $rsp = explode("\n", $response); + foreach ($rsp as $line) { + if (preg_match('|die_on_error) + die("The Flickr API returned the following error: #{$match[1]} - {$match[2]}"); + else { + $this->error_code = $match[1]; + $this->error_msg = $match[2]; + $this->parsed_response = false; + return false; + } + } elseif (preg_match("|<" . $find . ">(.*)error_code = false; + $this->error_msg = false; + return $match[1]; + } + } + } else { + die("Sorry, your server must support CURL in order to upload files"); + } + } + + function auth ($perms = "read", $remember_uri = true) { + // Redirects to Flickr's authentication piece if there is no valid token. + // If remember_uri is set to false, the callback script (included) will + // redirect to its default page. + + if (empty($_SESSION['phpFlickr_auth_token']) && empty($this->token)) { + if ( $remember_uri === true ) { + $_SESSION['phpFlickr_auth_redirect'] = $_SERVER['REQUEST_URI']; + } elseif ( $remember_uri !== false ) { + $_SESSION['phpFlickr_auth_redirect'] = $remember_uri; + } + $api_sig = md5($this->secret . "api_key" . $this->api_key . "perms" . $perms); + + if ($this->service == "23") { + header("Location: http://www.23hq.com/services/auth/?api_key=" . $this->api_key . "&perms=" . $perms . "&api_sig=". $api_sig); + } else { + header("Location: http://www.flickr.com/services/auth/?api_key=" . $this->api_key . "&perms=" . $perms . "&api_sig=". $api_sig); + } + exit; + } else { + $tmp = $this->die_on_error; + $this->die_on_error = false; + $rsp = $this->auth_checkToken(); + if ($this->error_code !== false) { + unset($_SESSION['phpFlickr_auth_token']); + $this->auth($perms, $remember_uri); + } + $this->die_on_error = $tmp; + return $rsp['perms']; + } + } + + /******************************* + + To use the phpFlickr::call method, pass a string containing the API method you want + to use and an associative array of arguments. For example: + $result = $f->call("flickr.photos.comments.getList", array("photo_id"=>'34952612')); + This method will allow you to make calls to arbitrary methods that haven't been + implemented in phpFlickr yet. + + *******************************/ + + function call ($method, $arguments) { + foreach ( $arguments as $key => $value ) { + if ( is_null($value) ) unset($arguments[$key]); + } + $this->request($method, $arguments); + return $this->parsed_response ? $this->parsed_response : false; + } + + /* + These functions are the direct implementations of flickr calls. + For method documentation, including arguments, visit the address + included in a comment in the function. + */ + + /* Activity methods */ + function activity_userComments ($per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.activity.userComments.html */ + $this->request('flickr.activity.userComments', array("per_page" => $per_page, "page" => $page)); + return $this->parsed_response ? $this->parsed_response['items']['item'] : false; + } + + function activity_userPhotos ($timeframe = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.activity.userPhotos.html */ + $this->request('flickr.activity.userPhotos', array("timeframe" => $timeframe, "per_page" => $per_page, "page" => $page)); + return $this->parsed_response ? $this->parsed_response['items']['item'] : false; + } + + /* Authentication methods */ + function auth_checkToken () { + /* http://www.flickr.com/services/api/flickr.auth.checkToken.html */ + $this->request('flickr.auth.checkToken'); + return $this->parsed_response ? $this->parsed_response['auth'] : false; + } + + function auth_getFrob () { + /* http://www.flickr.com/services/api/flickr.auth.getFrob.html */ + $this->request('flickr.auth.getFrob'); + return $this->parsed_response ? $this->parsed_response['frob'] : false; + } + + function auth_getFullToken ($mini_token) { + /* http://www.flickr.com/services/api/flickr.auth.getFullToken.html */ + $this->request('flickr.auth.getFullToken', array('mini_token'=>$mini_token)); + return $this->parsed_response ? $this->parsed_response['auth'] : false; + } + + function auth_getToken ($frob) { + /* http://www.flickr.com/services/api/flickr.auth.getToken.html */ + $this->request('flickr.auth.getToken', array('frob'=>$frob)); + $_SESSION['phpFlickr_auth_token'] = $this->parsed_response['auth']['token']; + return $this->parsed_response ? $this->parsed_response['auth'] : false; + } + + /* Blogs methods */ + function blogs_getList ($service = NULL) { + /* http://www.flickr.com/services/api/flickr.blogs.getList.html */ + $rsp = $this->call('flickr.blogs.getList', array('service' => $service)); + return $rsp['blogs']['blog']; + } + + function blogs_getServices () { + /* http://www.flickr.com/services/api/flickr.blogs.getServices.html */ + return $this->call('flickr.blogs.getServices', array()); + } + + function blogs_postPhoto ($blog_id = NULL, $photo_id, $title, $description, $blog_password = NULL, $service = NULL) { + /* http://www.flickr.com/services/api/flickr.blogs.postPhoto.html */ + return $this->call('flickr.blogs.postPhoto', array('blog_id' => $blog_id, 'photo_id' => $photo_id, 'title' => $title, 'description' => $description, 'blog_password' => $blog_password, 'service' => $service)); + } + + /* Collections Methods */ + function collections_getInfo ($collection_id) { + /* http://www.flickr.com/services/api/flickr.collections.getInfo.html */ + return $this->call('flickr.collections.getInfo', array('collection_id' => $collection_id)); + } + + function collections_getTree ($collection_id = NULL, $user_id = NULL) { + /* http://www.flickr.com/services/api/flickr.collections.getTree.html */ + return $this->call('flickr.collections.getTree', array('collection_id' => $collection_id, 'user_id' => $user_id)); + } + + /* Commons Methods */ + function commons_getInstitutions () { + /* http://www.flickr.com/services/api/flickr.commons.getInstitutions.html */ + return $this->call('flickr.commons.getInstitutions', array()); + } + + /* Contacts Methods */ + function contacts_getList ($filter = NULL, $page = NULL, $per_page = NULL) { + /* http://www.flickr.com/services/api/flickr.contacts.getList.html */ + $this->request('flickr.contacts.getList', array('filter'=>$filter, 'page'=>$page, 'per_page'=>$per_page)); + return $this->parsed_response ? $this->parsed_response['contacts'] : false; + } + + function contacts_getPublicList ($user_id, $page = NULL, $per_page = NULL) { + /* http://www.flickr.com/services/api/flickr.contacts.getPublicList.html */ + $this->request('flickr.contacts.getPublicList', array('user_id'=>$user_id, 'page'=>$page, 'per_page'=>$per_page)); + return $this->parsed_response ? $this->parsed_response['contacts'] : false; + } + + function contacts_getListRecentlyUploaded ($date_lastupload = NULL, $filter = NULL) { + /* http://www.flickr.com/services/api/flickr.contacts.getListRecentlyUploaded.html */ + return $this->call('flickr.contacts.getListRecentlyUploaded', array('date_lastupload' => $date_lastupload, 'filter' => $filter)); + } + + /* Favorites Methods */ + function favorites_add ($photo_id) { + /* http://www.flickr.com/services/api/flickr.favorites.add.html */ + $this->request('flickr.favorites.add', array('photo_id'=>$photo_id), TRUE); + return $this->parsed_response ? true : false; + } + + function favorites_getList ($user_id = NULL, $jump_to = NULL, $min_fave_date = NULL, $max_fave_date = NULL, $extras = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.favorites.getList.html */ + return $this->call('flickr.favorites.getList', array('user_id' => $user_id, 'jump_to' => $jump_to, 'min_fave_date' => $min_fave_date, 'max_fave_date' => $max_fave_date, 'extras' => $extras, 'per_page' => $per_page, 'page' => $page)); + } + + function favorites_getPublicList ($user_id, $jump_to = NULL, $min_fave_date = NULL, $max_fave_date = NULL, $extras = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.favorites.getPublicList.html */ + return $this->call('flickr.favorites.getPublicList', array('user_id' => $user_id, 'jump_to' => $jump_to, 'min_fave_date' => $min_fave_date, 'max_fave_date' => $max_fave_date, 'extras' => $extras, 'per_page' => $per_page, 'page' => $page)); + } + + function favorites_remove ($photo_id, $user_id = NULL) { + /* http://www.flickr.com/services/api/flickr.favorites.remove.html */ + $this->request("flickr.favorites.remove", array('photo_id' => $photo_id, 'user_id' => $user_id), TRUE); + return $this->parsed_response ? true : false; + } + + /* Galleries Methods */ + function galleries_addPhoto ($gallery_id, $photo_id, $comment = NULL) { + /* http://www.flickr.com/services/api/flickr.galleries.addPhoto.html */ + return $this->call('flickr.galleries.addPhoto', array('gallery_id' => $gallery_id, 'photo_id' => $photo_id, 'comment' => $comment)); + } + + function galleries_create ($title, $description, $primary_photo_id = NULL) { + /* http://www.flickr.com/services/api/flickr.galleries.create.html */ + return $this->call('flickr.galleries.create', array('title' => $title, 'description' => $description, 'primary_photo_id' => $primary_photo_id)); + } + + function galleries_editMeta ($gallery_id, $title, $description = NULL) { + /* http://www.flickr.com/services/api/flickr.galleries.editMeta.html */ + return $this->call('flickr.galleries.editMeta', array('gallery_id' => $gallery_id, 'title' => $title, 'description' => $description)); + } + + function galleries_editPhoto ($gallery_id, $photo_id, $comment) { + /* http://www.flickr.com/services/api/flickr.galleries.editPhoto.html */ + return $this->call('flickr.galleries.editPhoto', array('gallery_id' => $gallery_id, 'photo_id' => $photo_id, 'comment' => $comment)); + } + + function galleries_editPhotos ($gallery_id, $primary_photo_id, $photo_ids) { + /* http://www.flickr.com/services/api/flickr.galleries.editPhotos.html */ + return $this->call('flickr.galleries.editPhotos', array('gallery_id' => $gallery_id, 'primary_photo_id' => $primary_photo_id, 'photo_ids' => $photo_ids)); + } + + function galleries_getInfo ($gallery_id) { + /* http://www.flickr.com/services/api/flickr.galleries.getInfo.html */ + return $this->call('flickr.galleries.getInfo', array('gallery_id' => $gallery_id)); + } + + function galleries_getList ($user_id, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.galleries.getList.html */ + return $this->call('flickr.galleries.getList', array('user_id' => $user_id, 'per_page' => $per_page, 'page' => $page)); + } + + function galleries_getListForPhoto ($photo_id, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.galleries.getListForPhoto.html */ + return $this->call('flickr.galleries.getListForPhoto', array('photo_id' => $photo_id, 'per_page' => $per_page, 'page' => $page)); + } + + function galleries_getPhotos ($gallery_id, $extras = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.galleries.getPhotos.html */ + return $this->call('flickr.galleries.getPhotos', array('gallery_id' => $gallery_id, 'extras' => $extras, 'per_page' => $per_page, 'page' => $page)); + } + + /* Groups Methods */ + function groups_browse ($cat_id = NULL) { + /* http://www.flickr.com/services/api/flickr.groups.browse.html */ + $this->request("flickr.groups.browse", array("cat_id"=>$cat_id)); + return $this->parsed_response ? $this->parsed_response['category'] : false; + } + + function groups_getInfo ($group_id, $lang = NULL) { + /* http://www.flickr.com/services/api/flickr.groups.getInfo.html */ + return $this->call('flickr.groups.getInfo', array('group_id' => $group_id, 'lang' => $lang)); + } + + function groups_search ($text, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.groups.search.html */ + $this->request("flickr.groups.search", array("text"=>$text,"per_page"=>$per_page,"page"=>$page)); + return $this->parsed_response ? $this->parsed_response['groups'] : false; + } + + /* Groups Members Methods */ + function groups_members_getList ($group_id, $membertypes = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.groups.members.getList.html */ + return $this->call('flickr.groups.members.getList', array('group_id' => $group_id, 'membertypes' => $membertypes, 'per_page' => $per_page, 'page' => $page)); + } + + /* Groups Pools Methods */ + function groups_pools_add ($photo_id, $group_id) { + /* http://www.flickr.com/services/api/flickr.groups.pools.add.html */ + $this->request("flickr.groups.pools.add", array("photo_id"=>$photo_id, "group_id"=>$group_id), TRUE); + return $this->parsed_response ? true : false; + } + + function groups_pools_getContext ($photo_id, $group_id, $num_prev = NULL, $num_next = NULL) { + /* http://www.flickr.com/services/api/flickr.groups.pools.getContext.html */ + return $this->call('flickr.groups.pools.getContext', array('photo_id' => $photo_id, 'group_id' => $group_id, 'num_prev' => $num_prev, 'num_next' => $num_next)); + } + + function groups_pools_getGroups ($page = NULL, $per_page = NULL) { + /* http://www.flickr.com/services/api/flickr.groups.pools.getGroups.html */ + $this->request("flickr.groups.pools.getGroups", array('page'=>$page, 'per_page'=>$per_page)); + return $this->parsed_response ? $this->parsed_response['groups'] : false; + } + + function groups_pools_getPhotos ($group_id, $tags = NULL, $user_id = NULL, $jump_to = NULL, $extras = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.groups.pools.getPhotos.html */ + if (is_array($extras)) { + $extras = implode(",", $extras); + } + return $this->call('flickr.groups.pools.getPhotos', array('group_id' => $group_id, 'tags' => $tags, 'user_id' => $user_id, 'jump_to' => $jump_to, 'extras' => $extras, 'per_page' => $per_page, 'page' => $page)); + } + + function groups_pools_remove ($photo_id, $group_id) { + /* http://www.flickr.com/services/api/flickr.groups.pools.remove.html */ + $this->request("flickr.groups.pools.remove", array("photo_id"=>$photo_id, "group_id"=>$group_id), TRUE); + return $this->parsed_response ? true : false; + } + + /* Interestingness methods */ + function interestingness_getList ($date = NULL, $use_panda = NULL, $extras = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.interestingness.getList.html */ + if (is_array($extras)) { + $extras = implode(",", $extras); + } + + return $this->call('flickr.interestingness.getList', array('date' => $date, 'use_panda' => $use_panda, 'extras' => $extras, 'per_page' => $per_page, 'page' => $page)); + } + + /* Machine Tag methods */ + function machinetags_getNamespaces ($predicate = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.machinetags.getNamespaces.html */ + return $this->call('flickr.machinetags.getNamespaces', array('predicate' => $predicate, 'per_page' => $per_page, 'page' => $page)); + } + + function machinetags_getPairs ($namespace = NULL, $predicate = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.machinetags.getPairs.html */ + return $this->call('flickr.machinetags.getPairs', array('namespace' => $namespace, 'predicate' => $predicate, 'per_page' => $per_page, 'page' => $page)); + } + + function machinetags_getPredicates ($namespace = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.machinetags.getPredicates.html */ + return $this->call('flickr.machinetags.getPredicates', array('namespace' => $namespace, 'per_page' => $per_page, 'page' => $page)); + } + + function machinetags_getRecentValues ($namespace = NULL, $predicate = NULL, $added_since = NULL) { + /* http://www.flickr.com/services/api/flickr.machinetags.getRecentValues.html */ + return $this->call('flickr.machinetags.getRecentValues', array('namespace' => $namespace, 'predicate' => $predicate, 'added_since' => $added_since)); + } + + function machinetags_getValues ($namespace, $predicate, $per_page = NULL, $page = NULL, $usage = NULL) { + /* http://www.flickr.com/services/api/flickr.machinetags.getValues.html */ + return $this->call('flickr.machinetags.getValues', array('namespace' => $namespace, 'predicate' => $predicate, 'per_page' => $per_page, 'page' => $page, 'usage' => $usage)); + } + + /* Panda methods */ + function panda_getList () { + /* http://www.flickr.com/services/api/flickr.panda.getList.html */ + return $this->call('flickr.panda.getList', array()); + } + + function panda_getPhotos ($panda_name, $extras = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.panda.getPhotos.html */ + return $this->call('flickr.panda.getPhotos', array('panda_name' => $panda_name, 'extras' => $extras, 'per_page' => $per_page, 'page' => $page)); + } + + /* People methods */ + function people_findByEmail ($find_email) { + /* http://www.flickr.com/services/api/flickr.people.findByEmail.html */ + $this->request("flickr.people.findByEmail", array("find_email"=>$find_email)); + return $this->parsed_response ? $this->parsed_response['user'] : false; + } + + function people_findByUsername ($username) { + /* http://www.flickr.com/services/api/flickr.people.findByUsername.html */ + $this->request("flickr.people.findByUsername", array("username"=>$username)); + return $this->parsed_response ? $this->parsed_response['user'] : false; + } + + function people_getInfo ($user_id) { + /* http://www.flickr.com/services/api/flickr.people.getInfo.html */ + $this->request("flickr.people.getInfo", array("user_id"=>$user_id)); + return $this->parsed_response ? $this->parsed_response['person'] : false; + } + + function people_getPhotos ($user_id, $args = array()) { + /* This function strays from the method of arguments that I've + * used in the other functions for the fact that there are just + * so many arguments to this API method. What you'll need to do + * is pass an associative array to the function containing the + * arguments you want to pass to the API. For example: + * $photos = $f->photos_search(array("tags"=>"brown,cow", "tag_mode"=>"any")); + * This will return photos tagged with either "brown" or "cow" + * or both. See the API documentation (link below) for a full + * list of arguments. + */ + + /* http://www.flickr.com/services/api/flickr.people.getPhotos.html */ + return $this->call('flickr.people.getPhotos', array_merge(array('user_id' => $user_id), $args)); + } + + function people_getPhotosOf ($user_id, $extras = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.people.getPhotosOf.html */ + return $this->call('flickr.people.getPhotosOf', array('user_id' => $user_id, 'extras' => $extras, 'per_page' => $per_page, 'page' => $page)); + } + + function people_getPublicGroups ($user_id) { + /* http://www.flickr.com/services/api/flickr.people.getPublicGroups.html */ + $this->request("flickr.people.getPublicGroups", array("user_id"=>$user_id)); + return $this->parsed_response ? $this->parsed_response['groups']['group'] : false; + } + + function people_getPublicPhotos ($user_id, $safe_search = NULL, $extras = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.people.getPublicPhotos.html */ + return $this->call('flickr.people.getPublicPhotos', array('user_id' => $user_id, 'safe_search' => $safe_search, 'extras' => $extras, 'per_page' => $per_page, 'page' => $page)); + } + + function people_getUploadStatus () { + /* http://www.flickr.com/services/api/flickr.people.getUploadStatus.html */ + /* Requires Authentication */ + $this->request("flickr.people.getUploadStatus"); + return $this->parsed_response ? $this->parsed_response['user'] : false; + } + + + /* Photos Methods */ + function photos_addTags ($photo_id, $tags) { + /* http://www.flickr.com/services/api/flickr.photos.addTags.html */ + $this->request("flickr.photos.addTags", array("photo_id"=>$photo_id, "tags"=>$tags), TRUE); + return $this->parsed_response ? true : false; + } + + function photos_delete ($photo_id) { + /* http://www.flickr.com/services/api/flickr.photos.delete.html */ + $this->request("flickr.photos.delete", array("photo_id"=>$photo_id), TRUE); + return $this->parsed_response ? true : false; + } + + function photos_getAllContexts ($photo_id) { + /* http://www.flickr.com/services/api/flickr.photos.getAllContexts.html */ + $this->request("flickr.photos.getAllContexts", array("photo_id"=>$photo_id)); + return $this->parsed_response ? $this->parsed_response : false; + } + + function photos_getContactsPhotos ($count = NULL, $just_friends = NULL, $single_photo = NULL, $include_self = NULL, $extras = NULL) { + /* http://www.flickr.com/services/api/flickr.photos.getContactsPhotos.html */ + $this->request("flickr.photos.getContactsPhotos", array("count"=>$count, "just_friends"=>$just_friends, "single_photo"=>$single_photo, "include_self"=>$include_self, "extras"=>$extras)); + return $this->parsed_response ? $this->parsed_response['photos']['photo'] : false; + } + + function photos_getContactsPublicPhotos ($user_id, $count = NULL, $just_friends = NULL, $single_photo = NULL, $include_self = NULL, $extras = NULL) { + /* http://www.flickr.com/services/api/flickr.photos.getContactsPublicPhotos.html */ + $this->request("flickr.photos.getContactsPublicPhotos", array("user_id"=>$user_id, "count"=>$count, "just_friends"=>$just_friends, "single_photo"=>$single_photo, "include_self"=>$include_self, "extras"=>$extras)); + return $this->parsed_response ? $this->parsed_response['photos']['photo'] : false; + } + + function photos_getContext ($photo_id, $num_prev = NULL, $num_next = NULL, $extras = NULL, $order_by = NULL) { + /* http://www.flickr.com/services/api/flickr.photos.getContext.html */ + return $this->call('flickr.photos.getContext', array('photo_id' => $photo_id, 'num_prev' => $num_prev, 'num_next' => $num_next, 'extras' => $extras, 'order_by' => $order_by)); + } + + function photos_getCounts ($dates = NULL, $taken_dates = NULL) { + /* http://www.flickr.com/services/api/flickr.photos.getCounts.html */ + $this->request("flickr.photos.getCounts", array("dates"=>$dates, "taken_dates"=>$taken_dates)); + return $this->parsed_response ? $this->parsed_response['photocounts']['photocount'] : false; + } + + function photos_getExif ($photo_id, $secret = NULL) { + /* http://www.flickr.com/services/api/flickr.photos.getExif.html */ + $this->request("flickr.photos.getExif", array("photo_id"=>$photo_id, "secret"=>$secret)); + return $this->parsed_response ? $this->parsed_response['photo'] : false; + } + + function photos_getFavorites ($photo_id, $page = NULL, $per_page = NULL) { + /* http://www.flickr.com/services/api/flickr.photos.getFavorites.html */ + $this->request("flickr.photos.getFavorites", array("photo_id"=>$photo_id, "page"=>$page, "per_page"=>$per_page)); + return $this->parsed_response ? $this->parsed_response['photo'] : false; + } + + function photos_getInfo ($photo_id, $secret = NULL, $humandates = NULL, $privacy_filter = NULL, $get_contexts = NULL) { + /* http://www.flickr.com/services/api/flickr.photos.getInfo.html */ + return $this->call('flickr.photos.getInfo', array('photo_id' => $photo_id, 'secret' => $secret, 'humandates' => $humandates, 'privacy_filter' => $privacy_filter, 'get_contexts' => $get_contexts)); + } + + function photos_getNotInSet ($max_upload_date = NULL, $min_taken_date = NULL, $max_taken_date = NULL, $privacy_filter = NULL, $media = NULL, $min_upload_date = NULL, $extras = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.photos.getNotInSet.html */ + return $this->call('flickr.photos.getNotInSet', array('max_upload_date' => $max_upload_date, 'min_taken_date' => $min_taken_date, 'max_taken_date' => $max_taken_date, 'privacy_filter' => $privacy_filter, 'media' => $media, 'min_upload_date' => $min_upload_date, 'extras' => $extras, 'per_page' => $per_page, 'page' => $page)); + } + + function photos_getPerms ($photo_id) { + /* http://www.flickr.com/services/api/flickr.photos.getPerms.html */ + $this->request("flickr.photos.getPerms", array("photo_id"=>$photo_id)); + return $this->parsed_response ? $this->parsed_response['perms'] : false; + } + + function photos_getRecent ($jump_to = NULL, $extras = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.photos.getRecent.html */ + if (is_array($extras)) { + $extras = implode(",", $extras); + } + return $this->call('flickr.photos.getRecent', array('jump_to' => $jump_to, 'extras' => $extras, 'per_page' => $per_page, 'page' => $page)); + } + + function photos_getSizes ($photo_id) { + /* http://www.flickr.com/services/api/flickr.photos.getSizes.html */ + $this->request("flickr.photos.getSizes", array("photo_id"=>$photo_id)); + return $this->parsed_response ? $this->parsed_response['sizes']['size'] : false; + } + + function photos_getUntagged ($min_upload_date = NULL, $max_upload_date = NULL, $min_taken_date = NULL, $max_taken_date = NULL, $privacy_filter = NULL, $media = NULL, $extras = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.photos.getUntagged.html */ + return $this->call('flickr.photos.getUntagged', array('min_upload_date' => $min_upload_date, 'max_upload_date' => $max_upload_date, 'min_taken_date' => $min_taken_date, 'max_taken_date' => $max_taken_date, 'privacy_filter' => $privacy_filter, 'media' => $media, 'extras' => $extras, 'per_page' => $per_page, 'page' => $page)); + } + + function photos_getWithGeoData ($args = array()) { + /* See the documentation included with the photos_search() function. + * I'm using the same style of arguments for this function. The only + * difference here is that this doesn't require any arguments. The + * flickr.photos.search method requires at least one search parameter. + */ + /* http://www.flickr.com/services/api/flickr.photos.getWithGeoData.html */ + $this->request("flickr.photos.getWithGeoData", $args); + return $this->parsed_response ? $this->parsed_response['photos'] : false; + } + + function photos_getWithoutGeoData ($args = array()) { + /* See the documentation included with the photos_search() function. + * I'm using the same style of arguments for this function. The only + * difference here is that this doesn't require any arguments. The + * flickr.photos.search method requires at least one search parameter. + */ + /* http://www.flickr.com/services/api/flickr.photos.getWithoutGeoData.html */ + $this->request("flickr.photos.getWithoutGeoData", $args); + return $this->parsed_response ? $this->parsed_response['photos'] : false; + } + + function photos_recentlyUpdated ($min_date, $extras = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.photos.recentlyUpdated.html */ + return $this->call('flickr.photos.recentlyUpdated', array('min_date' => $min_date, 'extras' => $extras, 'per_page' => $per_page, 'page' => $page)); + } + + function photos_removeTag ($tag_id) { + /* http://www.flickr.com/services/api/flickr.photos.removeTag.html */ + $this->request("flickr.photos.removeTag", array("tag_id"=>$tag_id), TRUE); + return $this->parsed_response ? true : false; + } + + function photos_search ($args = array()) { + /* This function strays from the method of arguments that I've + * used in the other functions for the fact that there are just + * so many arguments to this API method. What you'll need to do + * is pass an associative array to the function containing the + * arguments you want to pass to the API. For example: + * $photos = $f->photos_search(array("tags"=>"brown,cow", "tag_mode"=>"any")); + * This will return photos tagged with either "brown" or "cow" + * or both. See the API documentation (link below) for a full + * list of arguments. + */ + + /* http://www.flickr.com/services/api/flickr.photos.search.html */ + $this->request("flickr.photos.search", $args); + return $this->parsed_response ? $this->parsed_response['photos'] : false; + } + + function photos_setContentType ($photo_id, $content_type) { + /* http://www.flickr.com/services/api/flickr.photos.setContentType.html */ + return $this->call('flickr.photos.setContentType', array('photo_id' => $photo_id, 'content_type' => $content_type)); + } + + function photos_setDates ($photo_id, $date_posted = NULL, $date_taken = NULL, $date_taken_granularity = NULL) { + /* http://www.flickr.com/services/api/flickr.photos.setDates.html */ + $this->request("flickr.photos.setDates", array("photo_id"=>$photo_id, "date_posted"=>$date_posted, "date_taken"=>$date_taken, "date_taken_granularity"=>$date_taken_granularity), TRUE); + return $this->parsed_response ? true : false; + } + + function photos_setMeta ($photo_id, $title, $description) { + /* http://www.flickr.com/services/api/flickr.photos.setMeta.html */ + $this->request("flickr.photos.setMeta", array("photo_id"=>$photo_id, "title"=>$title, "description"=>$description), TRUE); + return $this->parsed_response ? true : false; + } + + function photos_setPerms ($photo_id, $is_public, $is_friend, $is_family, $perm_comment, $perm_addmeta) { + /* http://www.flickr.com/services/api/flickr.photos.setPerms.html */ + $this->request("flickr.photos.setPerms", array("photo_id"=>$photo_id, "is_public"=>$is_public, "is_friend"=>$is_friend, "is_family"=>$is_family, "perm_comment"=>$perm_comment, "perm_addmeta"=>$perm_addmeta), TRUE); + return $this->parsed_response ? true : false; + } + + function photos_setSafetyLevel ($photo_id, $safety_level = NULL, $hidden = NULL) { + /* http://www.flickr.com/services/api/flickr.photos.setSafetyLevel.html */ + return $this->call('flickr.photos.setSafetyLevel', array('photo_id' => $photo_id, 'safety_level' => $safety_level, 'hidden' => $hidden)); + } + + function photos_setTags ($photo_id, $tags) { + /* http://www.flickr.com/services/api/flickr.photos.setTags.html */ + $this->request("flickr.photos.setTags", array("photo_id"=>$photo_id, "tags"=>$tags), TRUE); + return $this->parsed_response ? true : false; + } + + /* Photos - Comments Methods */ + function photos_comments_addComment ($photo_id, $comment_text) { + /* http://www.flickr.com/services/api/flickr.photos.comments.addComment.html */ + $this->request("flickr.photos.comments.addComment", array("photo_id" => $photo_id, "comment_text"=>$comment_text), TRUE); + return $this->parsed_response ? $this->parsed_response['comment'] : false; + } + + function photos_comments_deleteComment ($comment_id) { + /* http://www.flickr.com/services/api/flickr.photos.comments.deleteComment.html */ + $this->request("flickr.photos.comments.deleteComment", array("comment_id" => $comment_id), TRUE); + return $this->parsed_response ? true : false; + } + + function photos_comments_editComment ($comment_id, $comment_text) { + /* http://www.flickr.com/services/api/flickr.photos.comments.editComment.html */ + $this->request("flickr.photos.comments.editComment", array("comment_id" => $comment_id, "comment_text"=>$comment_text), TRUE); + return $this->parsed_response ? true : false; + } + + function photos_comments_getList ($photo_id, $min_comment_date = NULL, $max_comment_date = NULL, $page = NULL, $per_page = NULL, $include_faves = NULL) { + /* http://www.flickr.com/services/api/flickr.photos.comments.getList.html */ + return $this->call('flickr.photos.comments.getList', array('photo_id' => $photo_id, 'min_comment_date' => $min_comment_date, 'max_comment_date' => $max_comment_date, 'page' => $page, 'per_page' => $per_page, 'include_faves' => $include_faves)); + } + + function photos_comments_getRecentForContacts ($date_lastcomment = NULL, $contacts_filter = NULL, $extras = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.photos.comments.getRecentForContacts.html */ + return $this->call('flickr.photos.comments.getRecentForContacts', array('date_lastcomment' => $date_lastcomment, 'contacts_filter' => $contacts_filter, 'extras' => $extras, 'per_page' => $per_page, 'page' => $page)); + } + + /* Photos - Geo Methods */ + function photos_geo_batchCorrectLocation ($lat, $lon, $accuracy, $place_id = NULL, $woe_id = NULL) { + /* http://www.flickr.com/services/api/flickr.photos.geo.batchCorrectLocation.html */ + return $this->call('flickr.photos.geo.batchCorrectLocation', array('lat' => $lat, 'lon' => $lon, 'accuracy' => $accuracy, 'place_id' => $place_id, 'woe_id' => $woe_id)); + } + + function photos_geo_correctLocation ($photo_id, $place_id = NULL, $woe_id = NULL) { + /* http://www.flickr.com/services/api/flickr.photos.geo.correctLocation.html */ + return $this->call('flickr.photos.geo.correctLocation', array('photo_id' => $photo_id, 'place_id' => $place_id, 'woe_id' => $woe_id)); + } + + function photos_geo_getLocation ($photo_id) { + /* http://www.flickr.com/services/api/flickr.photos.geo.getLocation.html */ + $this->request("flickr.photos.geo.getLocation", array("photo_id"=>$photo_id)); + return $this->parsed_response ? $this->parsed_response['photo'] : false; + } + + function photos_geo_getPerms ($photo_id) { + /* http://www.flickr.com/services/api/flickr.photos.geo.getPerms.html */ + $this->request("flickr.photos.geo.getPerms", array("photo_id"=>$photo_id)); + return $this->parsed_response ? $this->parsed_response['perms'] : false; + } + + function photos_geo_photosForLocation ($lat, $lon, $accuracy = NULL, $extras = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.photos.geo.photosForLocation.html */ + return $this->call('flickr.photos.geo.photosForLocation', array('lat' => $lat, 'lon' => $lon, 'accuracy' => $accuracy, 'extras' => $extras, 'per_page' => $per_page, 'page' => $page)); + } + + function photos_geo_removeLocation ($photo_id) { + /* http://www.flickr.com/services/api/flickr.photos.geo.removeLocation.html */ + $this->request("flickr.photos.geo.removeLocation", array("photo_id"=>$photo_id), TRUE); + return $this->parsed_response ? true : false; + } + + function photos_geo_setContext ($photo_id, $context) { + /* http://www.flickr.com/services/api/flickr.photos.geo.setContext.html */ + return $this->call('flickr.photos.geo.setContext', array('photo_id' => $photo_id, 'context' => $context)); + } + + function photos_geo_setLocation ($photo_id, $lat, $lon, $accuracy = NULL, $context = NULL, $bookmark_id = NULL) { + /* http://www.flickr.com/services/api/flickr.photos.geo.setLocation.html */ + return $this->call('flickr.photos.geo.setLocation', array('photo_id' => $photo_id, 'lat' => $lat, 'lon' => $lon, 'accuracy' => $accuracy, 'context' => $context, 'bookmark_id' => $bookmark_id)); + } + + function photos_geo_setPerms ($is_public, $is_contact, $is_friend, $is_family, $photo_id) { + /* http://www.flickr.com/services/api/flickr.photos.geo.setPerms.html */ + return $this->call('flickr.photos.geo.setPerms', array('is_public' => $is_public, 'is_contact' => $is_contact, 'is_friend' => $is_friend, 'is_family' => $is_family, 'photo_id' => $photo_id)); + } + + /* Photos - Licenses Methods */ + function photos_licenses_getInfo () { + /* http://www.flickr.com/services/api/flickr.photos.licenses.getInfo.html */ + $this->request("flickr.photos.licenses.getInfo"); + return $this->parsed_response ? $this->parsed_response['licenses']['license'] : false; + } + + function photos_licenses_setLicense ($photo_id, $license_id) { + /* http://www.flickr.com/services/api/flickr.photos.licenses.setLicense.html */ + /* Requires Authentication */ + $this->request("flickr.photos.licenses.setLicense", array("photo_id"=>$photo_id, "license_id"=>$license_id), TRUE); + return $this->parsed_response ? true : false; + } + + /* Photos - Notes Methods */ + function photos_notes_add ($photo_id, $note_x, $note_y, $note_w, $note_h, $note_text) { + /* http://www.flickr.com/services/api/flickr.photos.notes.add.html */ + $this->request("flickr.photos.notes.add", array("photo_id" => $photo_id, "note_x" => $note_x, "note_y" => $note_y, "note_w" => $note_w, "note_h" => $note_h, "note_text" => $note_text), TRUE); + return $this->parsed_response ? $this->parsed_response['note'] : false; + } + + function photos_notes_delete ($note_id) { + /* http://www.flickr.com/services/api/flickr.photos.notes.delete.html */ + $this->request("flickr.photos.notes.delete", array("note_id" => $note_id), TRUE); + return $this->parsed_response ? true : false; + } + + function photos_notes_edit ($note_id, $note_x, $note_y, $note_w, $note_h, $note_text) { + /* http://www.flickr.com/services/api/flickr.photos.notes.edit.html */ + $this->request("flickr.photos.notes.edit", array("note_id" => $note_id, "note_x" => $note_x, "note_y" => $note_y, "note_w" => $note_w, "note_h" => $note_h, "note_text" => $note_text), TRUE); + return $this->parsed_response ? true : false; + } + + /* Photos - Transform Methods */ + function photos_transform_rotate ($photo_id, $degrees) { + /* http://www.flickr.com/services/api/flickr.photos.transform.rotate.html */ + $this->request("flickr.photos.transform.rotate", array("photo_id" => $photo_id, "degrees" => $degrees), TRUE); + return $this->parsed_response ? true : false; + } + + /* Photos - People Methods */ + function photos_people_add ($photo_id, $user_id, $person_x = NULL, $person_y = NULL, $person_w = NULL, $person_h = NULL) { + /* http://www.flickr.com/services/api/flickr.photos.people.add.html */ + return $this->call('flickr.photos.people.add', array('photo_id' => $photo_id, 'user_id' => $user_id, 'person_x' => $person_x, 'person_y' => $person_y, 'person_w' => $person_w, 'person_h' => $person_h)); + } + + function photos_people_delete ($photo_id, $user_id, $email = NULL) { + /* http://www.flickr.com/services/api/flickr.photos.people.delete.html */ + return $this->call('flickr.photos.people.delete', array('photo_id' => $photo_id, 'user_id' => $user_id, 'email' => $email)); + } + + function photos_people_deleteCoords ($photo_id, $user_id) { + /* http://www.flickr.com/services/api/flickr.photos.people.deleteCoords.html */ + return $this->call('flickr.photos.people.deleteCoords', array('photo_id' => $photo_id, 'user_id' => $user_id)); + } + + function photos_people_editCoords ($photo_id, $user_id, $person_x, $person_y, $person_w, $person_h, $email = NULL) { + /* http://www.flickr.com/services/api/flickr.photos.people.editCoords.html */ + return $this->call('flickr.photos.people.editCoords', array('photo_id' => $photo_id, 'user_id' => $user_id, 'person_x' => $person_x, 'person_y' => $person_y, 'person_w' => $person_w, 'person_h' => $person_h, 'email' => $email)); + } + + function photos_people_getList ($photo_id) { + /* http://www.flickr.com/services/api/flickr.photos.people.getList.html */ + return $this->call('flickr.photos.people.getList', array('photo_id' => $photo_id)); + } + + /* Photos - Upload Methods */ + function photos_upload_checkTickets ($tickets) { + /* http://www.flickr.com/services/api/flickr.photos.upload.checkTickets.html */ + if (is_array($tickets)) { + $tickets = implode(",", $tickets); + } + $this->request("flickr.photos.upload.checkTickets", array("tickets" => $tickets), TRUE); + return $this->parsed_response ? $this->parsed_response['uploader']['ticket'] : false; + } + + /* Photosets Methods */ + function photosets_addPhoto ($photoset_id, $photo_id) { + /* http://www.flickr.com/services/api/flickr.photosets.addPhoto.html */ + $this->request("flickr.photosets.addPhoto", array("photoset_id" => $photoset_id, "photo_id" => $photo_id), TRUE); + return $this->parsed_response ? true : false; + } + + function photosets_create ($title, $description, $primary_photo_id) { + /* http://www.flickr.com/services/api/flickr.photosets.create.html */ + $this->request("flickr.photosets.create", array("title" => $title, "primary_photo_id" => $primary_photo_id, "description" => $description), TRUE); + return $this->parsed_response ? $this->parsed_response['photoset'] : false; + } + + function photosets_delete ($photoset_id) { + /* http://www.flickr.com/services/api/flickr.photosets.delete.html */ + $this->request("flickr.photosets.delete", array("photoset_id" => $photoset_id), TRUE); + return $this->parsed_response ? true : false; + } + + function photosets_editMeta ($photoset_id, $title, $description = NULL) { + /* http://www.flickr.com/services/api/flickr.photosets.editMeta.html */ + $this->request("flickr.photosets.editMeta", array("photoset_id" => $photoset_id, "title" => $title, "description" => $description), TRUE); + return $this->parsed_response ? true : false; + } + + function photosets_editPhotos ($photoset_id, $primary_photo_id, $photo_ids) { + /* http://www.flickr.com/services/api/flickr.photosets.editPhotos.html */ + $this->request("flickr.photosets.editPhotos", array("photoset_id" => $photoset_id, "primary_photo_id" => $primary_photo_id, "photo_ids" => $photo_ids), TRUE); + return $this->parsed_response ? true : false; + } + + function photosets_getContext ($photo_id, $photoset_id, $num_prev = NULL, $num_next = NULL) { + /* http://www.flickr.com/services/api/flickr.photosets.getContext.html */ + return $this->call('flickr.photosets.getContext', array('photo_id' => $photo_id, 'photoset_id' => $photoset_id, 'num_prev' => $num_prev, 'num_next' => $num_next)); + } + + function photosets_getInfo ($photoset_id) { + /* http://www.flickr.com/services/api/flickr.photosets.getInfo.html */ + $this->request("flickr.photosets.getInfo", array("photoset_id" => $photoset_id)); + return $this->parsed_response ? $this->parsed_response['photoset'] : false; + } + + function photosets_getList ($user_id = NULL) { + /* http://www.flickr.com/services/api/flickr.photosets.getList.html */ + $this->request("flickr.photosets.getList", array("user_id" => $user_id)); + return $this->parsed_response ? $this->parsed_response['photosets'] : false; + } + + function photosets_getPhotos ($photoset_id, $extras = NULL, $privacy_filter = NULL, $per_page = NULL, $page = NULL, $media = NULL) { + /* http://www.flickr.com/services/api/flickr.photosets.getPhotos.html */ + return $this->call('flickr.photosets.getPhotos', array('photoset_id' => $photoset_id, 'extras' => $extras, 'privacy_filter' => $privacy_filter, 'per_page' => $per_page, 'page' => $page, 'media' => $media)); + } + + function photosets_orderSets ($photoset_ids) { + /* http://www.flickr.com/services/api/flickr.photosets.orderSets.html */ + if (is_array($photoset_ids)) { + $photoset_ids = implode(",", $photoset_ids); + } + $this->request("flickr.photosets.orderSets", array("photoset_ids" => $photoset_ids), TRUE); + return $this->parsed_response ? true : false; + } + + function photosets_removePhoto ($photoset_id, $photo_id) { + /* http://www.flickr.com/services/api/flickr.photosets.removePhoto.html */ + $this->request("flickr.photosets.removePhoto", array("photoset_id" => $photoset_id, "photo_id" => $photo_id), TRUE); + return $this->parsed_response ? true : false; + } + + function photosets_removePhotos ($photoset_id, $photo_ids) { + /* http://www.flickr.com/services/api/flickr.photosets.removePhotos.html */ + return $this->call('flickr.photosets.removePhotos', array('photoset_id' => $photoset_id, 'photo_ids' => $photo_ids)); + } + + function photosets_reorderPhotos ($photoset_id, $photo_ids) { + /* http://www.flickr.com/services/api/flickr.photosets.reorderPhotos.html */ + return $this->call('flickr.photosets.reorderPhotos', array('photoset_id' => $photoset_id, 'photo_ids' => $photo_ids)); + } + + function photosets_setPrimaryPhoto ($photoset_id, $photo_id) { + /* http://www.flickr.com/services/api/flickr.photosets.setPrimaryPhoto.html */ + return $this->call('flickr.photosets.setPrimaryPhoto', array('photoset_id' => $photoset_id, 'photo_id' => $photo_id)); + } + + /* Photosets Comments Methods */ + function photosets_comments_addComment ($photoset_id, $comment_text) { + /* http://www.flickr.com/services/api/flickr.photosets.comments.addComment.html */ + $this->request("flickr.photosets.comments.addComment", array("photoset_id" => $photoset_id, "comment_text"=>$comment_text), TRUE); + return $this->parsed_response ? $this->parsed_response['comment'] : false; + } + + function photosets_comments_deleteComment ($comment_id) { + /* http://www.flickr.com/services/api/flickr.photosets.comments.deleteComment.html */ + $this->request("flickr.photosets.comments.deleteComment", array("comment_id" => $comment_id), TRUE); + return $this->parsed_response ? true : false; + } + + function photosets_comments_editComment ($comment_id, $comment_text) { + /* http://www.flickr.com/services/api/flickr.photosets.comments.editComment.html */ + $this->request("flickr.photosets.comments.editComment", array("comment_id" => $comment_id, "comment_text"=>$comment_text), TRUE); + return $this->parsed_response ? true : false; + } + + function photosets_comments_getList ($photoset_id) { + /* http://www.flickr.com/services/api/flickr.photosets.comments.getList.html */ + $this->request("flickr.photosets.comments.getList", array("photoset_id"=>$photoset_id)); + return $this->parsed_response ? $this->parsed_response['comments'] : false; + } + + /* Places Methods */ + function places_find ($query) { + /* http://www.flickr.com/services/api/flickr.places.find.html */ + return $this->call('flickr.places.find', array('query' => $query)); + } + + function places_findByLatLon ($lat, $lon, $accuracy = NULL) { + /* http://www.flickr.com/services/api/flickr.places.findByLatLon.html */ + return $this->call('flickr.places.findByLatLon', array('lat' => $lat, 'lon' => $lon, 'accuracy' => $accuracy)); + } + + function places_getChildrenWithPhotosPublic ($place_id = NULL, $woe_id = NULL) { + /* http://www.flickr.com/services/api/flickr.places.getChildrenWithPhotosPublic.html */ + return $this->call('flickr.places.getChildrenWithPhotosPublic', array('place_id' => $place_id, 'woe_id' => $woe_id)); + } + + function places_getInfo ($place_id = NULL, $woe_id = NULL) { + /* http://www.flickr.com/services/api/flickr.places.getInfo.html */ + return $this->call('flickr.places.getInfo', array('place_id' => $place_id, 'woe_id' => $woe_id)); + } + + function places_getInfoByUrl ($url) { + /* http://www.flickr.com/services/api/flickr.places.getInfoByUrl.html */ + return $this->call('flickr.places.getInfoByUrl', array('url' => $url)); + } + + function places_getPlaceTypes () { + /* http://www.flickr.com/services/api/flickr.places.getPlaceTypes.html */ + return $this->call('flickr.places.getPlaceTypes', array()); + } + + function places_getShapeHistory ($place_id = NULL, $woe_id = NULL) { + /* http://www.flickr.com/services/api/flickr.places.getShapeHistory.html */ + return $this->call('flickr.places.getShapeHistory', array('place_id' => $place_id, 'woe_id' => $woe_id)); + } + + function places_getTopPlacesList ($place_type_id, $date = NULL, $woe_id = NULL, $place_id = NULL) { + /* http://www.flickr.com/services/api/flickr.places.getTopPlacesList.html */ + return $this->call('flickr.places.getTopPlacesList', array('place_type_id' => $place_type_id, 'date' => $date, 'woe_id' => $woe_id, 'place_id' => $place_id)); + } + + function places_placesForBoundingBox ($bbox, $place_type = NULL, $place_type_id = NULL, $recursive = NULL) { + /* http://www.flickr.com/services/api/flickr.places.placesForBoundingBox.html */ + return $this->call('flickr.places.placesForBoundingBox', array('bbox' => $bbox, 'place_type' => $place_type, 'place_type_id' => $place_type_id, 'recursive' => $recursive)); + } + + function places_placesForContacts ($place_type = NULL, $place_type_id = NULL, $woe_id = NULL, $place_id = NULL, $threshold = NULL, $contacts = NULL, $min_upload_date = NULL, $max_upload_date = NULL, $min_taken_date = NULL, $max_taken_date = NULL) { + /* http://www.flickr.com/services/api/flickr.places.placesForContacts.html */ + return $this->call('flickr.places.placesForContacts', array('place_type' => $place_type, 'place_type_id' => $place_type_id, 'woe_id' => $woe_id, 'place_id' => $place_id, 'threshold' => $threshold, 'contacts' => $contacts, 'min_upload_date' => $min_upload_date, 'max_upload_date' => $max_upload_date, 'min_taken_date' => $min_taken_date, 'max_taken_date' => $max_taken_date)); + } + + function places_placesForTags ($place_type_id, $woe_id = NULL, $place_id = NULL, $threshold = NULL, $tags = NULL, $tag_mode = NULL, $machine_tags = NULL, $machine_tag_mode = NULL, $min_upload_date = NULL, $max_upload_date = NULL, $min_taken_date = NULL, $max_taken_date = NULL) { + /* http://www.flickr.com/services/api/flickr.places.placesForTags.html */ + return $this->call('flickr.places.placesForTags', array('place_type_id' => $place_type_id, 'woe_id' => $woe_id, 'place_id' => $place_id, 'threshold' => $threshold, 'tags' => $tags, 'tag_mode' => $tag_mode, 'machine_tags' => $machine_tags, 'machine_tag_mode' => $machine_tag_mode, 'min_upload_date' => $min_upload_date, 'max_upload_date' => $max_upload_date, 'min_taken_date' => $min_taken_date, 'max_taken_date' => $max_taken_date)); + } + + function places_placesForUser ($place_type_id = NULL, $place_type = NULL, $woe_id = NULL, $place_id = NULL, $threshold = NULL, $min_upload_date = NULL, $max_upload_date = NULL, $min_taken_date = NULL, $max_taken_date = NULL) { + /* http://www.flickr.com/services/api/flickr.places.placesForUser.html */ + return $this->call('flickr.places.placesForUser', array('place_type_id' => $place_type_id, 'place_type' => $place_type, 'woe_id' => $woe_id, 'place_id' => $place_id, 'threshold' => $threshold, 'min_upload_date' => $min_upload_date, 'max_upload_date' => $max_upload_date, 'min_taken_date' => $min_taken_date, 'max_taken_date' => $max_taken_date)); + } + + function places_resolvePlaceId ($place_id) { + /* http://www.flickr.com/services/api/flickr.places.resolvePlaceId.html */ + $rsp = $this->call('flickr.places.resolvePlaceId', array('place_id' => $place_id)); + return $rsp ? $rsp['location'] : $rsp; + } + + function places_resolvePlaceURL ($url) { + /* http://www.flickr.com/services/api/flickr.places.resolvePlaceURL.html */ + $rsp = $this->call('flickr.places.resolvePlaceURL', array('url' => $url)); + return $rsp ? $rsp['location'] : $rsp; + } + + function places_tagsForPlace ($woe_id = NULL, $place_id = NULL, $min_upload_date = NULL, $max_upload_date = NULL, $min_taken_date = NULL, $max_taken_date = NULL) { + /* http://www.flickr.com/services/api/flickr.places.tagsForPlace.html */ + return $this->call('flickr.places.tagsForPlace', array('woe_id' => $woe_id, 'place_id' => $place_id, 'min_upload_date' => $min_upload_date, 'max_upload_date' => $max_upload_date, 'min_taken_date' => $min_taken_date, 'max_taken_date' => $max_taken_date)); + } + + /* Prefs Methods */ + function prefs_getContentType () { + /* http://www.flickr.com/services/api/flickr.prefs.getContentType.html */ + $rsp = $this->call('flickr.prefs.getContentType', array()); + return $rsp ? $rsp['person'] : $rsp; + } + + function prefs_getGeoPerms () { + /* http://www.flickr.com/services/api/flickr.prefs.getGeoPerms.html */ + return $this->call('flickr.prefs.getGeoPerms', array()); + } + + function prefs_getHidden () { + /* http://www.flickr.com/services/api/flickr.prefs.getHidden.html */ + $rsp = $this->call('flickr.prefs.getHidden', array()); + return $rsp ? $rsp['person'] : $rsp; + } + + function prefs_getPrivacy () { + /* http://www.flickr.com/services/api/flickr.prefs.getPrivacy.html */ + $rsp = $this->call('flickr.prefs.getPrivacy', array()); + return $rsp ? $rsp['person'] : $rsp; + } + + function prefs_getSafetyLevel () { + /* http://www.flickr.com/services/api/flickr.prefs.getSafetyLevel.html */ + $rsp = $this->call('flickr.prefs.getSafetyLevel', array()); + return $rsp ? $rsp['person'] : $rsp; + } + + /* Reflection Methods */ + function reflection_getMethodInfo ($method_name) { + /* http://www.flickr.com/services/api/flickr.reflection.getMethodInfo.html */ + $this->request("flickr.reflection.getMethodInfo", array("method_name" => $method_name)); + return $this->parsed_response ? $this->parsed_response : false; + } + + function reflection_getMethods () { + /* http://www.flickr.com/services/api/flickr.reflection.getMethods.html */ + $this->request("flickr.reflection.getMethods"); + return $this->parsed_response ? $this->parsed_response['methods']['method'] : false; + } + + /* Stats Methods */ + function stats_getCollectionDomains ($date, $collection_id = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.stats.getCollectionDomains.html */ + return $this->call('flickr.stats.getCollectionDomains', array('date' => $date, 'collection_id' => $collection_id, 'per_page' => $per_page, 'page' => $page)); + } + + function stats_getCollectionReferrers ($date, $domain, $collection_id = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.stats.getCollectionReferrers.html */ + return $this->call('flickr.stats.getCollectionReferrers', array('date' => $date, 'domain' => $domain, 'collection_id' => $collection_id, 'per_page' => $per_page, 'page' => $page)); + } + + function stats_getCollectionStats ($date, $collection_id) { + /* http://www.flickr.com/services/api/flickr.stats.getCollectionStats.html */ + return $this->call('flickr.stats.getCollectionStats', array('date' => $date, 'collection_id' => $collection_id)); + } + + function stats_getCSVFiles () { + /* http://www.flickr.com/services/api/flickr.stats.getCSVFiles.html */ + return $this->call('flickr.stats.getCSVFiles', array()); + } + + function stats_getPhotoDomains ($date, $photo_id = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.stats.getPhotoDomains.html */ + return $this->call('flickr.stats.getPhotoDomains', array('date' => $date, 'photo_id' => $photo_id, 'per_page' => $per_page, 'page' => $page)); + } + + function stats_getPhotoReferrers ($date, $domain, $photo_id = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.stats.getPhotoReferrers.html */ + return $this->call('flickr.stats.getPhotoReferrers', array('date' => $date, 'domain' => $domain, 'photo_id' => $photo_id, 'per_page' => $per_page, 'page' => $page)); + } + + function stats_getPhotosetDomains ($date, $photoset_id = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.stats.getPhotosetDomains.html */ + return $this->call('flickr.stats.getPhotosetDomains', array('date' => $date, 'photoset_id' => $photoset_id, 'per_page' => $per_page, 'page' => $page)); + } + + function stats_getPhotosetReferrers ($date, $domain, $photoset_id = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.stats.getPhotosetReferrers.html */ + return $this->call('flickr.stats.getPhotosetReferrers', array('date' => $date, 'domain' => $domain, 'photoset_id' => $photoset_id, 'per_page' => $per_page, 'page' => $page)); + } + + function stats_getPhotosetStats ($date, $photoset_id) { + /* http://www.flickr.com/services/api/flickr.stats.getPhotosetStats.html */ + return $this->call('flickr.stats.getPhotosetStats', array('date' => $date, 'photoset_id' => $photoset_id)); + } + + function stats_getPhotoStats ($date, $photo_id) { + /* http://www.flickr.com/services/api/flickr.stats.getPhotoStats.html */ + return $this->call('flickr.stats.getPhotoStats', array('date' => $date, 'photo_id' => $photo_id)); + } + + function stats_getPhotostreamDomains ($date, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.stats.getPhotostreamDomains.html */ + return $this->call('flickr.stats.getPhotostreamDomains', array('date' => $date, 'per_page' => $per_page, 'page' => $page)); + } + + function stats_getPhotostreamReferrers ($date, $domain, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.stats.getPhotostreamReferrers.html */ + return $this->call('flickr.stats.getPhotostreamReferrers', array('date' => $date, 'domain' => $domain, 'per_page' => $per_page, 'page' => $page)); + } + + function stats_getPhotostreamStats ($date) { + /* http://www.flickr.com/services/api/flickr.stats.getPhotostreamStats.html */ + return $this->call('flickr.stats.getPhotostreamStats', array('date' => $date)); + } + + function stats_getPopularPhotos ($date = NULL, $sort = NULL, $per_page = NULL, $page = NULL) { + /* http://www.flickr.com/services/api/flickr.stats.getPopularPhotos.html */ + return $this->call('flickr.stats.getPopularPhotos', array('date' => $date, 'sort' => $sort, 'per_page' => $per_page, 'page' => $page)); + } + + function stats_getTotalViews ($date = NULL) { + /* http://www.flickr.com/services/api/flickr.stats.getTotalViews.html */ + return $this->call('flickr.stats.getTotalViews', array('date' => $date)); + } + + /* Tags Methods */ + function tags_getClusterPhotos ($tag, $cluster_id) { + /* http://www.flickr.com/services/api/flickr.tags.getClusterPhotos.html */ + return $this->call('flickr.tags.getClusterPhotos', array('tag' => $tag, 'cluster_id' => $cluster_id)); + } + + function tags_getClusters ($tag) { + /* http://www.flickr.com/services/api/flickr.tags.getClusters.html */ + return $this->call('flickr.tags.getClusters', array('tag' => $tag)); + } + + function tags_getHotList ($period = NULL, $count = NULL) { + /* http://www.flickr.com/services/api/flickr.tags.getHotList.html */ + $this->request("flickr.tags.getHotList", array("period" => $period, "count" => $count)); + return $this->parsed_response ? $this->parsed_response['hottags'] : false; + } + + function tags_getListPhoto ($photo_id) { + /* http://www.flickr.com/services/api/flickr.tags.getListPhoto.html */ + $this->request("flickr.tags.getListPhoto", array("photo_id" => $photo_id)); + return $this->parsed_response ? $this->parsed_response['photo']['tags']['tag'] : false; + } + + function tags_getListUser ($user_id = NULL) { + /* http://www.flickr.com/services/api/flickr.tags.getListUser.html */ + $this->request("flickr.tags.getListUser", array("user_id" => $user_id)); + return $this->parsed_response ? $this->parsed_response['who']['tags']['tag'] : false; + } + + function tags_getListUserPopular ($user_id = NULL, $count = NULL) { + /* http://www.flickr.com/services/api/flickr.tags.getListUserPopular.html */ + $this->request("flickr.tags.getListUserPopular", array("user_id" => $user_id, "count" => $count)); + return $this->parsed_response ? $this->parsed_response['who']['tags']['tag'] : false; + } + + function tags_getListUserRaw ($tag = NULL) { + /* http://www.flickr.com/services/api/flickr.tags.getListUserRaw.html */ + return $this->call('flickr.tags.getListUserRaw', array('tag' => $tag)); + } + + function tags_getRelated ($tag) { + /* http://www.flickr.com/services/api/flickr.tags.getRelated.html */ + $this->request("flickr.tags.getRelated", array("tag" => $tag)); + return $this->parsed_response ? $this->parsed_response['tags'] : false; + } + + function test_echo ($args = array()) { + /* http://www.flickr.com/services/api/flickr.test.echo.html */ + $this->request("flickr.test.echo", $args); + return $this->parsed_response ? $this->parsed_response : false; + } + + function test_login () { + /* http://www.flickr.com/services/api/flickr.test.login.html */ + $this->request("flickr.test.login"); + return $this->parsed_response ? $this->parsed_response['user'] : false; + } + + function urls_getGroup ($group_id) { + /* http://www.flickr.com/services/api/flickr.urls.getGroup.html */ + $this->request("flickr.urls.getGroup", array("group_id"=>$group_id)); + return $this->parsed_response ? $this->parsed_response['group']['url'] : false; + } + + function urls_getUserPhotos ($user_id = NULL) { + /* http://www.flickr.com/services/api/flickr.urls.getUserPhotos.html */ + $this->request("flickr.urls.getUserPhotos", array("user_id"=>$user_id)); + return $this->parsed_response ? $this->parsed_response['user']['url'] : false; + } + + function urls_getUserProfile ($user_id = NULL) { + /* http://www.flickr.com/services/api/flickr.urls.getUserProfile.html */ + $this->request("flickr.urls.getUserProfile", array("user_id"=>$user_id)); + return $this->parsed_response ? $this->parsed_response['user']['url'] : false; + } + + function urls_lookupGallery ($url) { + /* http://www.flickr.com/services/api/flickr.urls.lookupGallery.html */ + return $this->call('flickr.urls.lookupGallery', array('url' => $url)); + } + + function urls_lookupGroup ($url) { + /* http://www.flickr.com/services/api/flickr.urls.lookupGroup.html */ + $this->request("flickr.urls.lookupGroup", array("url"=>$url)); + return $this->parsed_response ? $this->parsed_response['group'] : false; + } + + function urls_lookupUser ($url) { + /* http://www.flickr.com/services/api/flickr.photos.notes.edit.html */ + $this->request("flickr.urls.lookupUser", array("url"=>$url)); + return $this->parsed_response ? $this->parsed_response['user'] : false; + } + } +} + +if ( !class_exists('phpFlickr_pager') ) { + class phpFlickr_pager { + var $phpFlickr, $per_page, $method, $args, $results, $global_phpFlickr; + var $total = null, $page = 0, $pages = null, $photos, $_extra = null; + + + function phpFlickr_pager($phpFlickr, $method = null, $args = null, $per_page = 30) { + $this->per_page = $per_page; + $this->method = $method; + $this->args = $args; + $this->set_phpFlickr($phpFlickr); + } + + function set_phpFlickr($phpFlickr) { + if ( is_a($phpFlickr, 'phpFlickr') ) { + $this->phpFlickr = $phpFlickr; + if ( $this->phpFlickr->cache ) { + $this->args['per_page'] = 500; + } else { + $this->args['per_page'] = (int) $this->per_page; + } + } + } + + function __sleep() { + return array( + 'method', + 'args', + 'per_page', + 'page', + '_extra', + ); + } + + function load($page) { + $allowed_methods = array( + 'flickr.photos.search' => 'photos', + 'flickr.photosets.getPhotos' => 'photoset', + ); + if ( !in_array($this->method, array_keys($allowed_methods)) ) return false; + + if ( $this->phpFlickr->cache ) { + $min = ($page - 1) * $this->per_page; + $max = $page * $this->per_page - 1; + if ( floor($min/500) == floor($max/500) ) { + $this->args['page'] = floor($min/500) + 1; + $this->results = $this->phpFlickr->call($this->method, $this->args); + if ( $this->results ) { + $this->results = $this->results[$allowed_methods[$this->method]]; + $this->photos = array_slice($this->results['photo'], $min % 500, $this->per_page); + $this->total = $this->results['total']; + $this->pages = ceil($this->results['total'] / $this->per_page); + return true; + } else { + return false; + } + } else { + $this->args['page'] = floor($min/500) + 1; + $this->results = $this->phpFlickr->call($this->method, $this->args); + if ( $this->results ) { + $this->results = $this->results[$allowed_methods[$this->method]]; + + $this->photos = array_slice($this->results['photo'], $min % 500); + $this->total = $this->results['total']; + $this->pages = ceil($this->results['total'] / $this->per_page); + + $this->args['page'] = floor($min/500) + 2; + $this->results = $this->phpFlickr->call($this->method, $this->args); + if ( $this->results ) { + $this->results = $this->results[$allowed_methods[$this->method]]; + $this->photos = array_merge($this->photos, array_slice($this->results['photo'], 0, $max % 500 + 1)); + } + return true; + } else { + return false; + } + + } + } else { + $this->args['page'] = $page; + $this->results = $this->phpFlickr->call($this->method, $this->args); + if ( $this->results ) { + $this->results = $this->results[$allowed_methods[$this->method]]; + + $this->photos = $this->results['photo']; + $this->total = $this->results['total']; + $this->pages = $this->results['pages']; + return true; + } else { + return false; + } + } + } + + function get($page = null) { + if ( is_null($page) ) { + $page = $this->page; + } else { + $this->page = $page; + } + if ( $this->load($page) ) { + return $this->photos; + } + $this->total = 0; + $this->pages = 0; + return array(); + } + + function next() { + $this->page++; + if ( $this->load($this->page) ) { + return $this->photos; + } + $this->total = 0; + $this->pages = 0; + return array(); + } + + } +} + +?> diff --git a/web/lib/instagram_api/.gitignore b/web/lib/instagram_api/.gitignore new file mode 100644 index 0000000..aedafa6 --- /dev/null +++ b/web/lib/instagram_api/.gitignore @@ -0,0 +1,3 @@ +/config.xml +tmp/ +.DS_Store \ No newline at end of file diff --git a/web/lib/instagram_api/.travis.yml b/web/lib/instagram_api/.travis.yml new file mode 100644 index 0000000..bb17424 --- /dev/null +++ b/web/lib/instagram_api/.travis.yml @@ -0,0 +1,8 @@ +language: php +php: + - 5.3 + - 5.4 +branches: + only: + - master + - development \ No newline at end of file diff --git a/web/lib/instagram_api/LICENSE b/web/lib/instagram_api/LICENSE new file mode 100644 index 0000000..31e052d --- /dev/null +++ b/web/lib/instagram_api/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2011 randy sesser + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/web/lib/instagram_api/README.md b/web/lib/instagram_api/README.md new file mode 100644 index 0000000..059a3f9 --- /dev/null +++ b/web/lib/instagram_api/README.md @@ -0,0 +1,111 @@ +## Instaphp v1.0 + +This software is licensed under The MIT License. Please see the file named 'LICENSE' for futher details. + +### About +Instaphp is a small(ish) PHP library to access [Instagram's][0] [API][1]. It's +main goal was to be easy to use, lightweight and have as few dependencies as +possible. It's currently only compatible with PHP 5 >= 5.3 but there are +very few 5.3 features being used and it's relatively trivial to convert it +to versions < 5.3. + +Instaphp is currently being used to power [instaview.me](http://instaview.me). + +### Quickstart Guide +To get an idea of how the library works, it's best to understand the various +[endpoints][2] provided by the API itself. The Instagram API currently has eight +"endpoints" in which to retrieve data from their system: + +* Users +* Relationships +* Media +* Comments +* Likes +* Tags +* Locations +* Geographies (This is really a subscription based endpoint and not available in Instaphp, yet) + +In actuality, these eight endpoints can be summarized into four major endpoints: + +* Users +* Media +* Tags +* Locations + +Relationships are really an attribute of Users. Comments and Likes are both +attributes of Media. Geographies are also an attribute of Media however, that +particular endpoint is only available for subscriptions created for a particular +location. Currently, Instaphp does not have a mechanism that supports subscriptions. + +These four main "endpoints" are the basis for this library and allows a good +separation for the various data you can pull from Instagram. + +#### Example: Getting the current Popular photos + +```php +Media->Popular(); + +//-- Check if an error was returned from the API +if (empty($response->error)) + foreach ($response->data as $item) + printf('%s', $item->images->thumbnail->url, $item->images->thumbnail->width, $item->images->thumbnail->height, empty($item->caption->text) ? 'Untitled':$item->caption->text); +``` + +#### Example: Authentication + +Instagram uses oAuth to authenticate its users. That means you follow a link to +their site, login to their system, and grant an application access on your behalf. +It's a fairly common scheme for handling authentication without passing sensitive +data (e.g. your username and password) across (possibly) unsecure lines (e.g. non-https). + +For Instaphp, you must have an API Key, API Secret and callback URL in order for +oAuth to work. The basic flow looks like this: + +1. User clicks a link to "Login" +2. User lands on Instagram's site and enters username/password +3. Upon successful login, user is asked if they want to grant application access to their photos +4. If user allows access, Instagram redirects user to callback URL of application with a code +5. Application calls API with code to validate authentication +6. Application is then given an access token to "sign" the calls to the API + +Here's how it looks: + +```php +GetOAuthUri(); ?> + + + Login + + Users->Authenticate($code); + + //-- If no errors, grab the access_token (and cookie it, if desired) + if (empty($response->error)) { + $token = $response->auth->access_token; + setcookie('instaphp', $token, strtotime('30 days')); + //-- once you have a token, update the Instaphp instance so it passes the token for future calls + $api = Instaphp\Instaphp::Instance($token); + } + } +``` + +[0]: http://instagr.am/ +[1]: http://instagram.com/developer/ +[2]: http://instagram.com/developer/endpoints/ diff --git a/web/lib/instagram_api/config.php b/web/lib/instagram_api/config.php new file mode 100644 index 0000000..4cf04fa --- /dev/null +++ b/web/lib/instagram_api/config.php @@ -0,0 +1,145 @@ + + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author randy sesser + * @copyright 2011, randy sesser + * @license http://www.opensource.org/licenses/mit-license The MIT License + * @package Instaphp + * @filesource + */ + +namespace Instaphp { + + use \SimpleXMLElement; + + /** + * The Instaphp version. We pass this to Instagram as part of the User-Agent + */ + define('INSTAPHP_VERSION', '1.0'); + + /** + * Our Config class which extends the SimpleXMLElement class + * See {inline @link http://php.net/simplexmlelement SimplXMLElement} + * @package Instaphp + * @version 1.0 + * @author randy sesser + */ + class Config extends SimpleXMLElement + { + + /** + * A static instance property for creating an instance of the Config object + * @var Instaphp\Config + * @access private + */ + private static $_instance = null; + /** + * The path to the config.xml file + * @var string + * @access private + */ + private static $file = null; + + /** + * Singleton method since the SimpleXMLElement class is essentially "sealed" + * @return Config An instance of the Config object + */ + public static function Instance() + { + if (static::$file == null) + static::$file = realpath(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'config.xml'; + + if (!file_exists(static::$file)) { + trigger_error("No configuration found for Instaphp. Using sample file!", E_USER_WARNING); + static::$file = realpath(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'config.xml'; + } + + if (null == static::$_instance) + static::$_instance = new self(static::$file, null, true); + + return static::$_instance; + } + + /** + * A convenience method to build the OAuth URL to authenticate a user. + * the value in the config.xml file should contain some "tokens" that + * are replaced with other values in the config. + * @access public + * @return string The OAuth URL used to authenticate a user + */ + public function GetOAuthUri() + { + if (!isset($this->Instagram)) + return null; + + $path = $this->Instagram->OAuthPath; + $path = str_replace("{ClientId}", $this->Instagram->ClientId, $path); + $path = str_replace("{RedirectUri}", $this->Instaphp->RedirectUri, $path); + + if (!empty($this->Instagram->Scope)) + $path .= '&scope=' . $this->Instagram->Scope; + + return $this->Instagram->Endpoint . $path; + } + + /** + * A convenience method to build the OAuth URL used to retreive an access token + * @return string The URL used to retrieve the access token + */ + public function GetOAuthTokenUri() + { + if (!isset($this->Instagram)) + return null; + + return $this->Instagram->Endpoint . $this->Instagram->OAuthTokenPath; + } + + public function CacheSetting($name, $key) + { + $cache = $this->xpath("//Instaphp/Cache[@Engine='File']"); + if (empty($cache) || count($cache) == 0) + return null; + + $cache = $cache[0]; + + return $cache->Settings->Setting[$key]; + + } + + public function GetSection($section = null, \SimpleXMLElement $parent = null) + { + if (empty($section)) + return null; + + if (null !== $parent) + return $parent->xpath($section); + + return $this->xpath($section); + } + + } + +} + diff --git a/web/lib/instagram_api/instagram/instagrambase.php b/web/lib/instagram_api/instagram/instagrambase.php new file mode 100644 index 0000000..e3a6832 --- /dev/null +++ b/web/lib/instagram_api/instagram/instagrambase.php @@ -0,0 +1,231 @@ + + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author randy sesser + * @copyright 2011, randy sesser + * @license http://www.opensource.org/licenses/mit-license The MIT License + * @package Instaphp + * @filesource + */ + +namespace Instaphp\Instagram { + + use Instaphp\Config; + use Instaphp\Request; + use Instaphp\Response; + + /** + * Instaphp Base Instagram class. + * @package Instaphp + * @version 1.0 + * @author randy + */ + class InstagramBase + { + + /** + * The Instaphp Config object + * @var Config + * @access protected + */ + protected $config = null; + /** + * The base API path appended to the endpoint + * @var string + * @access protected + */ + protected $api_path; + /** + * Parameters passed to the API + * @var Array + * @access protected + */ + protected $default_params = array(); + /** + * The access token used to authenticate API calls + * @var string + * @access protected + */ + protected $access_token; + /** + * Our request object + * @var Request + * @access protected + */ + protected $request; + + /** + * THE parameters array passed to the API call + * + * @var array + * @access public + */ + public $parameters = array(); + + /** + * Constructor. + * If you inherit from this class, you must call the parent constructor + * @access public + */ + public function __construct($token = null) + { + $this->config = Config::Instance(); + $this->default_params['client_id'] = $this->config->Instagram->ClientId; + + if (!empty($token)) + $this->default_params['access_token'] = $token; + + $this->request = new Request(); + } + + /** + * A convenience method for making Get requests via the request + * @access protected + * @param string $url A url in which to make a request + * @param Array $params An associative array of key/value pairs to pass to the API + * @return Response + */ + protected function Get($url = null, $params = array()) + { + if (empty($url)) + trigger_error('A URL is required in ' . __METHOD__, E_USER_ERROR); + + if (!empty($params)) + $this->AddParams($params); + + return $this->request->Get($url, array_merge($this->default_params, $this->parameters))->response; + } + + /** + * A convenience method for making POST request via the request object + * @access protected + * @param string $url A url in which to make a POST request + * @param Array $params An associative array of key/value pairs to POST to the API + * @return Response + */ + protected function Post($url = null, $params = array()) + { + if (empty($url)) + trigger_error('A URL is required in ' . __METHOD__, E_USER_ERROR); + + if (!empty($params)) + $this->AddParams($params); + + return $this->request->Post($url, array_merge($this->default_params, $this->parameters))->response; + } + + /** + * A convenience method for making DELETE requests via the request object + * @access protected + * @param string $url A url in which to make a DELETE request + * @param Array $params An associative array of key/value pairs to pass to the API + * @return Response + */ + protected function Delete($url = null, $params = array()) + { + if (empty($url)) + trigger_error('A URL is required in ' . __METHOD__, E_USER_ERROR); + + if (!empty($params)) + $this->AddParams($params); + + return $this->request->Delete($url, array_merge($this->default_params, $this->parameters))->response; + } + + /** + * A convenience method that builds a base URL to the Instagram API based on + * values in the config.xml file and the $api_path property. + * @access protected + * @param string $path The path to append to the base URL to create the endpoint + * @param string $action The 'action' to append to the endpoint (not always used, but available) + * @return string The Instagram API endpoint + */ + protected function BuildUrl($path = null, $action = null) + { + $uri = $this->config->Instagram->Endpoint . '/' . $this->config->Instagram->Version; + + + if (!empty($path) && substr($path, 0, 1) !== '/') + $path = '/' . $path; + + $path = $this->api_path . $path; + + $uri .= $path; + + if (null !== $action) { + if (substr($action, 0, 1) !== '/') + $action = '/' . $action; + + if (substr($action, strlen($action) - 1, 1) !== '/') + $action .= '/'; + + $uri .= $action; + } + + return $uri; + } + + /** + * A convenience method for bulk adding querystring parameters + * to the API requests. Note that existing params will be over-written. + * @access public + * @param Array $params Associative array of key/value pairs to add + * @return void + */ + public function AddParams(Array $params = array()) + { + $this->parameters = $params; + } + + /** + * A convenience method for adding a single parameter to the querystring + * passed to the API. Note this will overwrite existing parameters with + * the same name. + * @access public + * @param string $name The parameter name + * @param string $value The value to pass + * @return void + */ + public function AddParam($name, $value) + { + if (!empty($name)) + $this->parameters[$name] = $value; + } + + /** + * A convenience method for removing parameters from the querystring. + * @access public + * @param string $name The name of the parameter to remove + * @return void + */ + public function RemoveParam($name) + { + if (isset($this->parameters[$name])) + unset($this->parameters[$name]); + } + + } + +} \ No newline at end of file diff --git a/web/lib/instagram_api/instagram/locations.php b/web/lib/instagram_api/instagram/locations.php new file mode 100644 index 0000000..0b95c9c --- /dev/null +++ b/web/lib/instagram_api/instagram/locations.php @@ -0,0 +1,109 @@ + + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author randy sesser + * @copyright 2011, randy sesser + * @license http://www.opensource.org/licenses/mit-license The MIT License + * @package Instaphp + * @filesource + */ + +namespace Instaphp\Instagram { + + use Instaphp\Config; + use Instaphp\Request; + use Instaphp\Response; + + /** + * Locations class + * Handles all Location based API requests + * @package Instaphp + * @version 1.0 + * @author randy sesser + */ + class Locations extends InstagramBase + { + + public function __construct($token = null) + { + parent::__construct($token); + $this->api_path = '/locations'; + } + + /** + * Gets information about a particular location + * @access public + * @param int $location_id A location ID + * @param string $token An access token + * @return Response + */ + public function Info($location_id) + { + return $this->Get($this->buildUrl($location_id)); + } + + /** + * Get recent media associated with a particular media + * @access public + * @param int $location_id A location ID + * @param string $token An access token + * @param Array $params An associative array of key/value pairs to pass to the API + * @return Response + */ + public function Recent($location_id, Array $params = array()) + { + if (!empty($params)) + $this->AddParams($params); + + return $this->Get($this->buildUrl($location_id . '/media/recent')); + } + + /** + * Search for media by latitude/longitude + * @access public + * @param string $token An access token + * @param Array $params An associative array of key/value pairs to pass to the API + * @return Response + */ + public function Search(Array $params = array()) + { + if (isset($params['lat'])) { + if (!isset($params['lng']) || empty($params['lng'])) + trigger_error('Longitude and Latitude are mutually inclusive in ' . __METHOD__, E_USER_ERROR); + } + if (isset($params['lng'])) { + if (!isset($params['lat']) || empty($params['lat'])) + trigger_error('Longitude and Latitude are mutually inclusive in ' . __METHOD__, E_USER_ERROR); + } + + if (!empty($params)) + $this->AddParams($params); + + return $this->Get($this->buildUrl('search')); + } + + } + +} \ No newline at end of file diff --git a/web/lib/instagram_api/instagram/media.php b/web/lib/instagram_api/instagram/media.php new file mode 100644 index 0000000..06f6dd9 --- /dev/null +++ b/web/lib/instagram_api/instagram/media.php @@ -0,0 +1,185 @@ + + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author randy sesser + * @copyright 2011, randy sesser + * @license http://www.opensource.org/licenses/mit-license The MIT License + * @package Instaphp + * @filesource + */ + +namespace Instaphp\Instagram { + + use Instaphp\Config; + use Instaphp\Request; + use Instaphp\Response; + + /** + * Media + * The Media class handles all media requests to the API + * @package Instaphp + * @version 1.0 + * @author randy sesser + */ + class Media extends InstagramBase + { + public function __construct($token = null) + { + parent::__construct($token); + $this->api_path = '/media'; + } + + /** + * Gets information about a particular media + * @access public + * @param int $media_id A media ID + * @param string $token An access token + * @return Response + */ + public function Info($media_id) + { + return $this->Get($this->buildUrl($media_id)); + } + + /** + * Searches the API + * @access public + * @param string $token An access token + * @param Array $params An associative array of key/value pairs to pass to the API + * @return Response + */ + public function Search(Array $params = array()) + { + + if (isset($params['lat'])) { + if (!isset($params['lng']) || empty($params['lng'])) + trigger_error('Longitude and Latitude are mutually inclusive in ' . __METHOD__, E_USER_ERROR); + } + if (isset($params['lng'])) { + if (!isset($params['lat']) || empty($params['lat'])) + trigger_error('Longitude and Latitude are mutually inclusive in ' . __METHOD__, E_USER_ERROR); + } + + if (!empty($params)) + $this->AddParams($params); + + return $this->Get($this->buildUrl('search')); + } + + public function OEmbed($url) + { + $uri = $this->config->Instagram->Endpoint . '/' . $this->config->Instagram->Version; + return $this->Get($uri.'/oembed', array('url' => $url)); + } + + /** + * Gets the recent popular media. + * Note: This method does not appear to require authentication + * @access public + * @return Response + */ + public function Popular() + { + return $this->Get($this->BuildUrl('popular')); + } + + /** + * Gets comments associated with a particular media + * @access public + * @param int $media_id A media ID + * @param string $token An access token + * @return Response + */ + public function Comments($media_id) + { + return $this->Get($this->buildUrl($media_id . '/comments')); + } + + /** + * Adds a comment to a particular media + * @access public + * @param int $media_id A media ID + * @param string $comment The text of the comment + * @param string $token An access token + * @return Response + */ + public function Comment($media_id, $comment) + { + $this->AddParam('text', $comment); + return $this->Post($this->buildUrl($media_id . '/comments')); + } + + /** + * Deletes a comment previously left on a particular media + * @access public + * @param int $media_id A media ID + * @param int $comment_id The comment ID to delete + * @param string $token An access token + * @return Response + */ + public function DeleteComment($media_id, $comment_id) + { + return $this->Delete($this->buildUrl($media_id . '/comments/' . $comment_id)); + } + + /** + * Gets likes for a particular media + * @access public + * @param int $media_id A media ID + * @param string $token An access token + * @return Response + */ + public function Likes($media_id) + { + return $this->Get($this->buildUrl($media_id . '/likes')); + } + + /** + * Likes a particular media + * @access public + * @param int $media_id A media ID + * @param string $token An access token + * @return Response + */ + public function Like($media_id) + { + return $this->Post($this->buildUrl($media_id . '/likes')); + } + + /** + * Unlikes a particular media + * @access public + * @param int $media_id A media ID + * @param string $token An access token + * @return Response + */ + public function Unlike($media_id) + { + return $this->Delete($this->buildUrl($media_id . '/likes')); + } + + } + +} \ No newline at end of file diff --git a/web/lib/instagram_api/instagram/tags.php b/web/lib/instagram_api/instagram/tags.php new file mode 100644 index 0000000..b3209b7 --- /dev/null +++ b/web/lib/instagram_api/instagram/tags.php @@ -0,0 +1,101 @@ + + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author randy sesser + * @copyright 2011, randy sesser + * @license http://www.opensource.org/licenses/mit-license The MIT License + * @package Instaphp + * @filesource + */ + +namespace Instaphp\Instagram { + + use Instaphp\Config; + use Instaphp\Request; + use Instaphp\Response; + + /** + * Tags + * The Tags class handles all tag based API calls + * @package Instaphp + * @version 1.0 + * @author randy sesser + */ + class Tags extends InstagramBase + { + + public function __construct($token = null) + { + parent::__construct($token); + $this->api_path = '/tags'; + } + + /** + * Gets infor about a particular tag + * @access public + * @param string $tag A tag name + * @param string $token An access token + * @return Response + */ + public function Info($tag = mull) + { + if (empty($tag)) + trigger_error("You didn't supply a tag, not sure what whill happen here...", E_USER_WARNING); + + return $this->Get($this->buildUrl($tag)); + } + + /** + * Gets recent media tagged with $tag + * @access public + * @param string $tag A tag name + * @param string $token An access token + * @param Array $params An associative array of key/value pairs to pass to the API + * @return Response + */ + public function Recent($tag, Array $params = array()) + { + if (!empty($params)) + $this->AddParams($params); + + return $this->Get($this->buildUrl($tag . '/media/recent')); + } + + /** + * Searches for media by tag + * @access public + * @param string $query + * @param string $token + * @return Response + */ + public function Search($query = '') + { + $this->AddParam('q', $query); + return $this->Get($this->buildUrl('search')); + } + + } + +} \ No newline at end of file diff --git a/web/lib/instagram_api/instagram/users.php b/web/lib/instagram_api/instagram/users.php new file mode 100644 index 0000000..a8ad81d --- /dev/null +++ b/web/lib/instagram_api/instagram/users.php @@ -0,0 +1,274 @@ + + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author randy sesser + * @copyright 2011, randy sesser + * @license http://www.opensource.org/licenses/mit-license The MIT License + * @package Instaphp + * @filesource + */ + +namespace Instaphp\Instagram { + + use Instaphp\Config; + use Instaphp\Request; + use Instaphp\Response; + + /** + * Users + * The Users class handles all users request to the API + * @package Instaphp + * @version 1.0 + * @author randy sesser + */ + class Users extends InstagramBase + { + + public function __construct($token = null) + { + parent::__construct($token); + $this->api_path = '/users'; + } + + /** + * Gets the access token from an oAuth request + * @access public + * @param string $code The authorization code returned by the oAuth call + * @param string $scope The scope of the oAuth request + * @return Response + */ + public function Authenticate($code, $scope = null) + { + if (!empty($code)) { + $this->AddParams(array( + 'code' => $code, + 'client_secret' => $this->config->Instagram->ClientSecret, + 'grant_type' => 'authorization_code', + 'redirect_uri' => $this->config->Instaphp->RedirectUri + )); + + return $this->Post($this->config->GetOAuthTokenUri()); + } + } + + /** + * Gets info about a particular user + * @access public + * @param mixed $user_id A user ID or 'self' to get info about the currently authenticated user + * @return Response + */ + public function Info($user_id = 'self') + { + return $this->Get($this->buildUrl($user_id)); + } + + /** + * Gets a users feed + * @access public + * @param string $token An access token + * @param Array $params An associative array of key/value pairs to pass to the API. + * @return Response + */ + public function Feed(Array $params = array()) + { + if (!empty($params)) + $this->AddParams($params); + + return $this->Get($this->buildUrl('self/feed/')); + } + + /** + * Gets a user most recent media + * @access public + * @param mixed $user_id A user ID or 'self' to get info about the currently authenticated user + * @param Array $params An associative array of key/value pairs to pass to the API + * @return Response + */ + public function Recent($user_id, Array $params = array()) + { + if (!empty($params)) + $this->AddParams($params); + + return $this->Get($this->buildUrl($user_id . '/media/recent/')); + } + + /** + * Gets media liked by the current user + * @access public + * @param Array $params An associative array of key/value pairs to pass to the API + * @return Response + */ + public function Liked(Array $params = array()) + { + if (!empty($params)) + $this->AddParams($params); + return $this->Get($this->buildUrl('self/media/liked/')); + } + + /** + * Search for a user by username + * @access public + * @param string $query A username + * @return Response + */ + public function Find($query = '') + { + $this->AddParam('q', $query); + return $this->Get($this->buildUrl('search')); + } + + /** + * Gets followers of a particular user + * @access public + * @param mixed $user_id A user ID or 'self' to get info about the currently authenticated user + * @param Array $params Additional params to pass to the API + * @return Response + */ + public function Following($user_id, Array $params = array()) + { + if (!empty($params)) + $this->AddParams($params); + + return $this->Get($this->buildUrl($user_id . '/follows')); + } + + /** + * Gets a user's followers + * @access public + * @param mixed $user_id A user ID or 'self' to get info about the currently authenticated user + * @param Array $params Additional params to pass to the API + * @return Response + */ + public function Followers($user_id, Array $params = array()) + { + if (!empty($params)) + $this->AddParams($params); + + return $this->Get($this->buildUrl($user_id . '/followed-by')); + } + + /** + * Gets requests for follows for a particular user + * @access public + * @param mixed $user_id A user ID or 'self' to get info about the currently authenticated user + * @return Response + */ + public function Requests($user_id) + { + + } + + /** + * Gets the relationship of a user based on the currently authenticated user + * @access public + * @param mixed $user_id A user ID or 'self' to get info about the currently authenticated user + * @return Response + */ + public function Relationship($user_id) + { + return $this->Get($this->buildUrl($user_id . '/relationship')); + } + + /** + * Sets a relationship between a particular user and the currently authenticated user + * @access public + * @param int $user_id A user ID + * @param Array $token An associative array of key/value pairs to pass to the API + * @return Response + */ + protected function SetRelationship($user_id, $action) + { + $this->AddParam('action', $action); + return $this->Post($this->buildUrl($user_id . '/relationship')); + } + + /** + * Follow a user... + * @access public + * @param int $user_id A user ID + * @return Response + */ + public function Follow($user_id) + { + return $this->SetRelationship($user_id, 'follow'); + } + + /** + * Unfollow a user... + * @access public + * @param int $user_id A user ID + * @return Response + */ + public function Unfollow($user_id) + { + return $this->SetRelationship($user_id, 'unfollow'); + } + + /** + * Block a user... + * @access public + * @param int $user_id A user ID + * @return Response + */ + public function Block($user_id) + { + return $this->SetRelationship($user_id, 'block'); + } + + /** + * Unblock a user... + * @access public + * @param int $user_id A user ID + * @return Response + */ + public function Unblock($user_id) + { + $this->SetRelationship($user_id, 'unblock'); + } + + /** + * Approve a user request... + * @access public + * @param int $user_id A user ID + * @return Response + */ + public function Approve($user_id) + { + $this->SetRelationship($user_id, 'approve'); + } + + /** + * Deny a user request... + * @access public + * @param int $user_id A user ID + * @return Response + */ + public function Deny($user_id) + { + $this->SetRelationship($user_id, 'deny'); + } + } + +} \ No newline at end of file diff --git a/web/lib/instagram_api/instaphp.php b/web/lib/instagram_api/instaphp.php new file mode 100644 index 0000000..d81df65 --- /dev/null +++ b/web/lib/instagram_api/instaphp.php @@ -0,0 +1,109 @@ + + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author randy sesser + * @copyright 2011, randy sesser + * @license http://www.opensource.org/licenses/mit-license The MIT License + * @package Instaphp + * @filesource + */ + +namespace Instaphp { + + $dirname = dirname(__FILE__).'/'; + + require_once( $dirname. 'config.php'); + require_once( $dirname. 'webrequest.php'); + require_once( $dirname. 'request.php'); + require_once( $dirname. 'response.php'); + require_once( $dirname. 'instagram/instagrambase.php'); + require_once( $dirname. 'instagram/users.php'); + require_once( $dirname. 'instagram/media.php'); + require_once( $dirname. 'instagram/tags.php'); + require_once( $dirname. 'instagram/locations.php'); + + /** + * A simple base class used to instantiate the various other API classes + * @package Instaphp + * @version 1.0 + * @author randy sesser + */ + class Instaphp + { + + /** + * @var Users + * @access public + */ + public $Users = null; + /** + * @var Media + * @access public + */ + public $Media = null; + /** + * @var Tags + * @access public + */ + public $Tags = null; + /** + * @var Locations + */ + public $Locations = null; + + /** + * Contains the last API url called + * + * @var string + **/ + public $url = null; + + private static $instance = null; + /** + * The constructor constructs, but only for itself + */ + final private function __construct($token = null) + { + $this->Users = new Instagram\Users($token); + $this->Media = new Instagram\Media($token); + $this->Tags = new Instagram\Tags($token); + $this->Locations = new Instagram\Locations($token); + } + + /** + * I AM SINGLETON + * We don't need to go instantiating all these objects more than once here + * @return Instaphp + */ + public static function Instance($token = null) + { + if (self::$instance == null || !empty($token)) { + self::$instance = new self($token); + } + return self::$instance; + } + } + +} diff --git a/web/lib/instagram_api/instaphpexception.php b/web/lib/instagram_api/instaphpexception.php new file mode 100644 index 0000000..8620fd4 --- /dev/null +++ b/web/lib/instagram_api/instaphpexception.php @@ -0,0 +1,18 @@ + + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author randy sesser + * @copyright 2011, randy sesser + * @license http://www.opensource.org/licenses/mit-license The MIT License + * @package Instaphp + * @filesource + */ + +namespace Instaphp { + + use Instaphp\Config; + use Instaphp\Cache; + use Instaphp\WebRequest; + /** + * Request + * The Request class performs simple curl requests to a URL optionally passing + * parameters on the querystring. Currently, it supports GET,POST and DELETE requests. + * @package Instaphp + * @version 1.0 + * @author randy sesser + */ + class Request + { + + /** + * Associative array of key/value pairs to pass to the Instagram API + * @var Array + * @access public + */ + public $parameters = array(); + /** + * The URL in which to make the request + * @var String + * @access public + */ + public $url = null; + /** + * A var to store whether or not to use curl + * @var boolean + * @access private + */ + private $useCurl = false; + + /** + * + * @var iCache Cache object used for caching + * @access private + */ + private $_cache = null; + + /** + * The constructor contructs + * @param string $url A URL in which to create a new request (optional) + * @param Array $params An associated array of key/value pairs to pass to said URL (optional) + */ + public function __construct($url = null, $params = array()) + { + $this->useCurl = self::HasCurl(); + $this->parameters = $params; + $this->url = $url; + +/* + $cacheConfig = Config::Instance()->GetSection("Instaphp/Cache"); + if (!empty($cacheConfig) && count($cacheConfig) > 0) { + $cacheConfig = $cacheConfig[0]; + if ($cacheConfig["Enabled"]) { + $engine = (string)$cacheConfig["Engine"]; + $this->_cache = Cache\Cache::Instance($engine); + // $method = new \ReflectionMethod("Instaphp\\Cache\\".$engine, 'Instance'); + // $this->_cache = $method->invoke(null, null); + // $this->_cache = Cache\File::Instance(); + } + + } +*/ + } + + + /** + * Makes a GET request + * @param string $url A URL in which to make a GET request + * @param Array $params An associative array of key/value pairs to pass to said URL + * @return Request + */ + public function Get($url = null, $params = array()) + { + if (null !== $url) + $this->url = $url; + + if (!empty($params)) + $this->parameters = $params; + $query = ''; + foreach ($this->parameters as $k => $v) + $query .= ((strlen ($query) == 0) ? '?' : '&') . sprintf('%s=%s', $k, $v); + + if (null !== $this->_cache) { + $key = sha1($url.$query); + + if (false === ($response = $this->_cache->Get($key))) { + $response = $this->GetResponse(); + if (empty ($response->error)) { + $this->_cache->Set($key, $response); + } + } + } else { + $response = $this->GetResponse(); + } + + $this->response = $response; + return $this; + } + + /** + * Makes a POST request + * @param string $url A URL in which to make a POST request + * @param Array $params An associative array of key/value pairs to pass to said URL + * @return Request + */ + public function Post($url = null, $params = array()) + { + if (null !== $url) + $this->url = $url; + + if (!empty($params)) + $this->parameters = $params; + + $this->response = $this->GetResponse('POST'); + return $this; + } + + /** + * Makes a PUT request (currently unused) + * @param string $url A URL in which to make a PUT request + * @param Array $params An associative array of key/value pairs to pass to said URL + * @return void + */ + public function Put($url = null, $params = array()) + { + + } + + /** + * Makes a DELETE request + * @param string $url A URL in which to make a DELETE request + * @param Array $params An associative array of key/value pairs to pass to said URL + * @return Request + */ + public function Delete($url = null, $params = array()) + { + if (null !== $url) + $this->url = $url; + + if (!empty($params)) + $this->parameters = $params; + + $this->response = $this->GetResponse('DELETE'); + return $this; + } + + /** + * Makes a request + * @param string $url A URL in which to make a GET request + * @param Array $params An associative array of key/value pairs to pass to said URL + * @access private + * @return Response + */ + private function GetResponse($method = 'GET') + { + //-- since there's no option to use anything other curl, this check is kinda useless + //-- I had high hopes with this one using sockets and whatnot, but alas, time is of + //-- the essence... in internet time + if ($this->useCurl) { + + $response = new Response; + + $http = WebRequest::Instance(); + $res = $http->Create($this->url, $method, $this->parameters); + + if ($res instanceof Error) + return $res; + + $response->info = $res->Info; + $response->json = $res->Content; + $response = Response::Create($this, $response); + return $response; + } + } + + /** + * Checks to see if cURL extension is available + * @access private + * @return boolean + */ + private static function HasCurl() + { + return function_exists('curl_init'); + } + + /** + * Determines whether or not curl will follow redirects over SSL + * See the constructor for details, but there are cases in which + * if curl can't verify the certificate of an SSL request, AND + * PHP is in safe_mode OR there are open_basedir restrictions, it will + * not follow a redirect. There's a fix for this that involves + * parsing all the response headers from a request and detecting + * a Location header, but that's kind of a hack as it bypasses the + * whole point of SSL. This method left for posterity. Or something... + * + * @return boolean + * @access private + **/ + private function WillFollowRedirects() + { + $open_basedir = ini_get('open_basedir'); + $safe_mode = strtolower(ini_get('safe_mode')); + if (empty($open_basedir) && $safe_mode == 'off') { + return true; + } + return false; + } + + } +} diff --git a/web/lib/instagram_api/response.php b/web/lib/instagram_api/response.php new file mode 100644 index 0000000..d4ed79e --- /dev/null +++ b/web/lib/instagram_api/response.php @@ -0,0 +1,279 @@ + + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author randy sesser + * @copyright 2011, randy sesser + * @license http://www.opensource.org/licenses/mit-license The MIT License + * @package Instaphp + * @filesource + */ + +namespace Instaphp { + /** + * The Response object. + * This is the object passed back to the caller of this framework. It mimcs + * Instagram's JSON objects returned from most (if not all) of its current + * endpoints. Not all properties will be populated, so isset() should be used + * when dealing with a response object's properties + * @package Instaphp + * @version 1.0 + * @author randy sesser + */ + class Response + { + /** + * Technical information about the http response + * + * @var array + * @access public + */ + public $info; + /** + * The meta "object" (contains a status code. 200 when successful) + * @var object + * @access public + */ + public $meta = null; + /** + * The data "object" contains everything. Too much to list here. + * See {@link https://api.instagram.com/developer/ Instagram Developer API} + * @var object + * @access public + */ + public $data = null; + /** + * The pagination "object" is not your typical pagination + * @var object + * @access public + */ + public $pagination = null; + /** + * If an error occurred, this will be populated. Check here first. + * + * if (!empty(\$response->error)) { + * echo \$response->error->message; + * } + * + * @var Error + * @access public + */ + public $error = null; + /** + * When authenticating, this is populated with the access token and basic + * user info returned from the API + * @var object + * @access public + */ + public $auth = null; + /** + * For embeded calls + * + * @var object + * @access public + **/ + public $embed = null; + /** + * This is the raw JSON response returned from the API. Usefull if + * you just want a "passthrough" situation or perhaps you want to embed + * the JSON string in the page and parse it with JavaScript. + * + * var response = JSON.parse('json ?>'); + * + * @var string + * @access public + */ + public $json = ''; + + public function __construct() + { + + } + + /** + * A convenience method to parse the response text and build a Response object + * @access public + * @static + * @param string $responseText The response from the API call + * @param string $url The url used to generate the Response object + * @return Response + */ + public static function Create(Request $request, Response $response) + { + $obj = json_decode($response->json); + + //-- for embeded calls, just return the embeded object + if (isset($obj->{'provider_url'}) && !empty($obj->{'provider_url'})) { + $response->embed = $obj; + return $response; + } + + if (empty($obj)) { + $error = new Error; + $error->type = 'cURLResponseError'; + $error->code = $response->info['http_code']; + $error->url = $response->info['url']; + switch ($error->code) + { + case 505: + $error->message = 'HTTP version not supported? Weird.'; + break; + case 504: + $error->message = 'Gateway timeout. Sorry.'; + break; + case 503: + $error->message = 'The API is currently unavailable'; + break; + case 502: + $error->message = 'Baaaaaaaaad gateway!'; + break; + case 501: + $error->message = 'Sorry, not implemented... YET.'; + break; + case 500: + $error->message = 'Whoops! API just barfed on your new shoes.'; + break; + case 405: + $error->message = 'Method not allowed.'; + break; + case 404: + $error->message = 'Received a 404 from the API'; + break; + case 403: + $error->message = 'The API says you are forbidden'; + break; + case 402: + $error->message = 'The API claims you own them money.'; + break; + case 401: + $error->message = 'The API says you are unauthorized.'; + break; + case 400: + $error->message = 'POBR... Plain Old Bad Request.'; + break; + default: + $error->message = 'Unknown error ocurred making this request'; + break; + } + $response->error = $error; + } + + if (isset($obj->{'error_message'})) { + $response->error = new Error($obj->{'error_type'}, $obj->{'code'}, $obj->{'error_message'}, $response->info['url']); + } + + if (isset($obj->{'access_token'})) { + $response->auth->access_token = $obj->{'access_token'}; + $response->auth->user = $obj->{'user'}; + } + + if (isset($obj->{'meta'})) + $response->meta = $obj->{'meta'}; + + if (isset($obj->{'meta'}) && $obj->{'meta'}->code !== 200) { + $response->error = new Error($response->meta->error_type, $response->meta->code, $response->meta->error_message, $response->info['url']); + $query = ''; + + } + + if (isset($obj->{'data'})) + $response->data = $obj->{'data'}; + + if (isset($obj->{'pagination'})) + $response->pagination = $obj->{'pagination'}; + + return $response; + } + + private static function fixNonUtf8Chars($data) + { + $aux = str_split($data); + foreach($aux as $a) { + $a1 = urlencode($a); + $aa = explode("%", $a1); + + foreach($aa as $v) + if($v!="") + if(hexdec($v)>127) + $data = str_replace($a,"&#".hexdec($v).";",$data); + + } + + return $data; + } + } + + /** + * Error Object + * + * + * @package Instaphp + * @version 1.0 + * @author randy sesser + */ + class Error + { + /** + * Error Type + * @var string + * @access public + */ + public $type = null; + /** + * Error Code + * @var int + * @access public + */ + public $code = null; + /** + * Error Message + * @var string + * @access public + */ + public $message = null; + /** + * The url associated with this error + * + * @var string + * @access public + **/ + public $url = null; + + /** + * The constructor constructs + * @param string $type The error type + * @param int $code The error code + * @param string $message The error message + * @return Error + * @access public + */ + public function __construct($type = null, $code = null, $message = null, $url = null) + { + $this->type = $type; + $this->code = $code; + $this->message = $message; + $this->url = $url; + } + } + +} \ No newline at end of file diff --git a/web/lib/instagram_api/webrequest.php b/web/lib/instagram_api/webrequest.php new file mode 100644 index 0000000..4dce0c7 --- /dev/null +++ b/web/lib/instagram_api/webrequest.php @@ -0,0 +1,284 @@ + + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author randy sesser + * @copyright 2011, randy sesser + * @license http://www.opensource.org/licenses/mit-license The MIT License + * @package Instaphp + * @filesource + */ +namespace Instaphp +{ + class WebRequest + { + /** + * + * @var resource A cURL multi handle resource + * @access private + */ + private $mh = null; + + /** + * + * @var array Array of active requests + * @access private + */ + private $_requests; + + /** + * + * @var array Array of stored responses + * @access private + */ + private $_responses; + /** + * + * @var array Array of common cURL options + * @access private + */ + private $_options = array( + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_HEADER => false, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_CONNECTTIMEOUT => 2, + CURLOPT_TIMEOUT => 10, + CURLOPT_ENCODING => '' + ); + + /** + * + * @var WebRequest An instance of WebRequest (aka Mr. Singleton) + * @access private + */ + static $_instance = null; + + /** + * Constructor is private final. Can only be instantiated via WebRequest::Instance() + * @access private + * @final + */ + private final function __construct() + { + $this->mh = curl_multi_init(); + + if (isset(Config::Instance()->Endpoint['timeout'])) + $this->_options[CURLOPT_TIMEOUT] = Config::Instance()->Endpoint['timeout']; + + $this->_options[CURLOPT_USERAGENT] = 'Instaphp/v' . INSTAPHP_VERSION; + + //-- this is an interesting hack to make curl+ssl+windows follow redirects + //-- without skipping verification. For some reason, the version of libcurl/curl + //-- included with ZendServer CE doesn't use the systems CA bundle, so, we specify + //-- the path to the cert here (via config setting) + if (isset(Config::Instance()->Instaphp->CACertBundlePath) && !empty(Config::Instance()->Instaphp->CACertBundlePath)) { + $this->_options[CURLOPT_SSL_VERIFYPEER] = true; + $this->_options[CURLOPT_SSL_VERIFYHOST] = 2; + $this->_options[CURLOPT_SSLVERSION] = 3; + $this->_options[CURLOPT_CAINFO] = Config::Instance()->Instaphp->CACertBundlePath; + } + + $this->_options[CURLOPT_HTTPHEADER] = array( + "Connection: keep-alive", + "Keep-Alive: 300", + "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7", + "Accept-Language: en-us,en;q=0.5" + ); + + $this->_requests = array(); + $this->_responses = array(); + } + + /** + * Instantiates a new WebRequest if one does not already exist + * + * @return WebRequest A single instance of WebRequest + * @access public + * @static + */ + public static function Instance() + { + if (null == static::$_instance) + static::$_instance = new self(); + return static::$_instance; + } + + /** + * Convenience method for http GET requests + * + * @param string $url The url to Get + * @param array $parameters An array of key/value pairs to pass + * @return WebRequestManager A WebRequestManager to manage the current request + * @access public + */ + public function Get($url, $parameters = array()) + { + return $this->Create($url, "GET", $parameters); + } + + /** + * Convenience method for http POST requests + * + * @param string $url The url to POST + * @param array $parameters An array of key/value pairs to pass + * @return WebRequestManager A WebRequestManager to manage the current request + * @access public + */ + public function Post($url, $parameters = array()) + { + return $this->Create($url, "POST", $parameters); + } + + /** + * Convenience method for http DELETE requests + * + * @param string $url The url to DELETE + * @param array $parameters An array of key/value pairs to pass + * @return WebRequestManager A WebRequestManager to manage the current request + * @access public + */ + public function Delete($url, $parameters = array()) + { + return $this->Create($url, "DELETE", $parameters); + } + + /** + * Creates a new cURL reuest and adds to the request queue for processing + * @param string $url The url in which to make the request + * @param string $method The method used to make the request [GET|POST|DELETE] + * @param array $parameters Array of key/value pairs to pass to the request + * @return mixed A WebRequestManager to manage the current request on success, Error on failure + * @access public + */ + public function Create($url, $method = 'GET', $parameters = array()) + { + $ch = curl_init(); + $key= (string)$ch; + $query = ''; + $res = null; + + $options = $this->_options; + + foreach ($parameters as $k => $v) + $query .= ((strlen ($query) == 0) ? "":"&") . sprintf('%s=%s', $k, urlencode($v)); + + switch (strtolower($method)) + { + case 'post': + $options[CURLOPT_POST] = true; + $options[CURLOPT_POSTFIELDS] = $query; + break; + case 'delete': + $options[CURLOPT_CUSTOMREQUEST] = 'DELETE'; + $url .= '?' . $query; + break; + default: + $url .= '?' . $query; + break; + } + + $options[CURLOPT_URL] = $url; + curl_setopt_array($ch, $options); + + $this->_requests[$key] = $ch; + + $res = curl_multi_add_handle($this->mh, $this->_requests[$key]); + if ($res == CURLM_OK) { + curl_multi_exec($this->mh, $active); + return new WebRequestManager($key); + } + return new Error('cURLError', curl_error($ch), curl_errno($ch), $options[CURLOPT_URL]); + } + + /** + * + * @param string $key The key used to get the current request from the queue + * @return WebResponse A WebResponse for the $key + * @access public + */ + public function GetResponse($key = null) + { + if (isset($this->_responses[$key])) + return $this->_responses[$key]; + + $running = null; + + do { + $res = curl_multi_exec($this->mh, $current); + if (null !== $running && $current != $running) { + $this->store(); + + if (isset($this->_responses[$key])) + return $this->_responses[$key]; + + } + $running = $current; + } while ($current > 0); + + return false; + } + + /** + * Runs through the request queue and processes completed requests + * @access private + */ + private function store() + { + while ($finished = curl_multi_info_read($this->mh, $messages)) { + $key = (string)$finished["handle"]; + $this->_responses[$key] = new WebResponse(curl_multi_getcontent($finished["handle"]), curl_getinfo($finished["handle"])); + curl_multi_remove_handle($this->mh, $finished["handle"]); + } + } + } + + class WebRequestManager + { + private $key; + private $request; + + public function __construct($key) + { + $this->key = $key; + $this->request = WebRequest::Instance(); + } + + public function __get($name) + { + $response = $this->request->GetResponse($this->key); + return $response->{$name}; + } + } + + class WebResponse + { + public $Content; + public $Info; + + public function __construct($content = null, $info = null) + { + $this->Content = $content; + $this->Info = $info; + } + } +} \ No newline at end of file diff --git a/web/module/imagehosting/ImageDO.php b/web/module/imagehosting/ImageDO.php new file mode 100644 index 0000000..dda007f --- /dev/null +++ b/web/module/imagehosting/ImageDO.php @@ -0,0 +1,96 @@ + + */ +class ImageDO extends SimpleImage implements Image { + + // ----------------------------------------------- + // Private properties + // ----------------------------------------------- + + /** + * Image table used to manage table with image data. + * + * @var ImageTable + */ + private $imageTable; + + /** + * Image's user. + * + * @var string + */ + private $user; + + // ----------------------------------------------- + // Constructor + // ----------------------------------------------- + + /** + * @param ImageTable $imageTable - ImageTable object used to perform operations with image table + * @param $id - id of the image + * @param $url - image's url + * @param $name - image's name + * @param string|null $user - image's user + */ + public function __construct(ImageTable $imageTable, $id, $url, $name, $user = null) { + parent::__construct($id, $url, $name); + $this->imageTable = $imageTable; + $this->user = $user; + $imageTable->insertOrUpdate($this->getId(), $this->getTableValues()); + } + + // ----------------------------------------------- + // Public methods + // ----------------------------------------------- + + /** + * Sets the user of the image. + * + * @param $user - user's name + */ + public function setUser($user) { + $this->user = $user; + } + + // ----------------------------------------------- + // Overridden methods (from Image) + // ----------------------------------------------- + + public function setDescription($description) { + parent::setDescription($description); + $this->imageTable->updateDescription($this->getId(), $this->getDescription()); + } + + public function removeDescription() { + parent::removeDescription(); + $this->imageTable->updateDescription($this->getId(), $this->getDescription()); + } + + public function setFavorite($is) { + $this->imageTable->updateFavorite($this->getId(), $this->isFavorite()); + } + + // ----------------------------------------------- + // Private methods + // ----------------------------------------------- + + /** + * Gets the values to insert into the table. + * + * @return array + */ + private function getTableValues() { + return array( $this->getId(), + $this->user, + $this->getUrl(), + $this->getName(), + $this->getDescription(), + $this->isFavorite()); + } + +} \ No newline at end of file diff --git a/web/module/imagehosting/ImageHostingController.php b/web/module/imagehosting/ImageHostingController.php new file mode 100644 index 0000000..68f2428 --- /dev/null +++ b/web/module/imagehosting/ImageHostingController.php @@ -0,0 +1,207 @@ + + */ +class ImageHostingController { + + // ----------------------------------------------- + // Private properties + // ----------------------------------------------- + + /** + * Concrete external service provides access to the external image services. + * + * @var ExternalService + */ + private $service; + + /** + * Service factory helps to create specific external service. + * + * @var ExternalServiceFactory + */ + private $serviceFactory; + + /** + * Database used to store image data. + * + * @var Database + */ + private $database; + + /** + * Image table used to manage table with image data. + * + * @var ImageTable + */ + private $imageTable; + + /** + * User with its own session. + * + * @var User + */ + private $user; + + // ----------------------------------------------- + // Constructor + // ----------------------------------------------- + + /** + * @param $dbServer - mysql server address + * @param $dbUsername - mysql server username + * @param $dbPassword - mysql server password + * @param $dbName - database name used to store image hosting service data + */ + public function __construct($dbServer, $dbUsername, $dbPassword, $dbName) { + $this->serviceFactory = ExternalServiceFactory::getInstance(); + $this->database = new MysqlDatabase($dbServer, $dbUsername, $dbPassword, $dbName); + $this->imageTable = new ImageTable($this->database); + $this->user = new User(); + } + + // ----------------------------------------------- + // Public methods + // ----------------------------------------------- + + /** + * Outputs all previously generated images, except favorite images. + */ + public function showGeneratedImages() { + $list = $this->imageTable->getListByUser($this->user->getName()); + $this->printImageTable($list); + } + + /** + * Shows images that were tagged as "favorite" images. + */ + public function showFavoriteImages() { + $list = $this->imageTable->getFavoriteList($this->user->getName()); + $this->printImageTable($list); + } + + /** + * Generates images from specific service. + * + * @param $serviceName - service images from will be generated + */ + public function generateImages($serviceName) { + + $this->removeNonFavoriteImages(); + + if ($serviceName == 'flikr') { + $this->service = $this->serviceFactory->createFlikrService(); + } else if ($serviceName == 'instagram') { + $this->service = $this->serviceFactory->createInstagramService(); + } + + $images = $this->service->loadMetadata(); + $dbImages = array(); + + foreach ($images as $image) { + $i = new ImageDO( $this->imageTable, + $image->getId(), + $image->getUrl(), + $image->getName(), + $this->user->getName()); + $i->setDescription(""); + $dbImages[] = $i->toArray(); + } + + $this->printImages($dbImages); + } + + /** + * Sets image with specific id as favorite. + * + * @param $id - id of the image in the database + */ + public function addFavoriteImage($id) { + $this->imageTable->updateFavorite($id, true); + } + + /** + * Removes favorite status of the image. + * + * @param $id - id of the image in the database + */ + public function removeFavoriteImage($id) { + $this->imageTable->delete($id); + //$this->imageTable->updateFavorite($id, false); + } + + /** + * Sets the description of the image. + * + * @param $id - id of the image in the database + * @param $description - new image description + */ + public function setImageDescription($id, $description) { + $this->imageTable->updateDescription($id, $description); + } + + /** + * Removes image's description. + * + * @param $id - id of the image in the database + */ + public function removeImageDescription($id) { + $this->imageTable->updateDescription($id, ""); + } + + /** + * Removes all generated images (including favorite) of the current user. + */ + public function removeImages() { + $this->imageTable->deleteByUser($this->user->getName()); + } + + // ----------------------------------------------- + // Private methods + // ----------------------------------------------- + + /** + * Removes all random images (non favorite) of the current user. + */ + private function removeNonFavoriteImages() { + $this->imageTable->deleteWithFavoriteStatus($this->user->getName(), false); + } + + /** + * Outputs image list that has been retrieved from the images table. + * + * @param $list + */ + private function printImageTable($list) { + + if ($list == null || count($list) == 0) + return; + + + $images = array(); + foreach ($list as $row) { + $i = new SimpleImage( $row[ImageTable::FIELD_ID], + $row[ImageTable::FIELD_URL], + $row[ImageTable::FIELD_NAME]); + $i->setDescription($row[ImageTable::FIELD_DESCRIPTION]); + $i->setFavorite($row[ImageTable::FIELD_FAVORITE]); + $images[] = $i->toArray(); + } + + $this->printImages($images); + } + + /** + * Prints the array to the output stream in json format. + * + * @param array $images + */ + private function printImages(array $images) { + if ($images != null && count($images) > 0) + echo json_encode($images); + } + +} \ No newline at end of file diff --git a/web/module/imagehosting/ImageTable.php b/web/module/imagehosting/ImageTable.php new file mode 100644 index 0000000..5025b2a --- /dev/null +++ b/web/module/imagehosting/ImageTable.php @@ -0,0 +1,193 @@ + + */ +class ImageTable extends SimpleTable { + + // ----------------------------------------------- + // Constants + // ----------------------------------------------- + + /** + * Table's name. + */ + const TABLE_NAME = 'images'; + + /** + * Table field. Image's id. + */ + const FIELD_ID = 'id'; + + /** + * Table field. Image's user. + */ + const FIELD_USER = 'user'; + + /** + * Table field. Image's url. + */ + const FIELD_URL = 'url'; + + /** + * Table field. Image's name. + */ + const FIELD_NAME = 'name'; + + /** + * Table field. Image's description. + */ + const FIELD_DESCRIPTION = 'description'; + + /** + * Table field. Indicates if image is favorite or not. + */ + const FIELD_FAVORITE = 'isFavorite'; + + // ----------------------------------------------- + // Constructor + // ----------------------------------------------- + + /** + * @param Database $database - database used to work with this table + */ + public function __construct(Database $database) { + parent::__construct(self::TABLE_NAME, $database); + } + + // ----------------------------------------------- + // Public methods + // ----------------------------------------------- + + /** + * Gets the list of the rows only with specific user name. + * + * @param $user - the user name + * @return null|array + */ + public function getListByUser($user) { + $condition = $this->getUserCondition($user) . " AND `" . self::FIELD_FAVORITE . "`='0'"; + return $this->getDatabase()->select(self::TABLE_NAME, + null, + $condition, + $this->getTablePrimaryRow(), + null); + } + + /** + * Gets the list of favorite images of the specific user. + * + * @param $user - the user name + * @return null|array + */ + public function getFavoriteList($user) { + $condition = $this->getUserCondition($user) . " AND `" . self::FIELD_FAVORITE . "`='1'"; + return $this->getDatabase()->select(self::TABLE_NAME, + null, + $condition, + $this->getTablePrimaryRow(), + null); + } + + /** + * Updates description of the specific image. + * + * @param $id - id of the image in the database + * @param $description - new image's description + * @return bool + */ + public function updateDescription($id, $description) { + // TODO: so rough. change. + $description = htmlspecialchars(mysql_real_escape_string($description)); + return $this->getDatabase()->update(self::TABLE_NAME, + array(self::FIELD_DESCRIPTION), + array($description), + $this->getPrimaryCondition($id)); + } + + /** + * Deletes all images binded to specific user. + * + * @param $user - user which images will be deleted + * @return bool + */ + public function deleteByUser($user) { + return $this->getDatabase()->delete(self::TABLE_NAME, "`" . self::FIELD_USER . "`='$user'"); + } + + /** + * Deletes all rows with specific favorite status. + * + * @param $user - user which images will be deleted + * @param $favoriteStatus - with this favorite status data will be removed + * @return bool + */ + public function deleteWithFavoriteStatus($user, $favoriteStatus) { + return $this->getDatabase()->delete(self::TABLE_NAME, "`" . self::FIELD_USER . "`='$user' AND " + . self::FIELD_FAVORITE . "='" . ($favoriteStatus ? '1' : '0') . "'"); + } + + /** + * Updates image status - sets its status to favorite or not. + * + * @param $id - id of the image in the database + * @param $isFavorite - set the image favorite or not favorite + * @return bool + */ + public function updateFavorite($id, $isFavorite) { + return $this->getDatabase()->update(self::TABLE_NAME, + array(self::FIELD_FAVORITE), + array($isFavorite ? '1' : '0'), + $this->getPrimaryCondition($id)); + } + + // ----------------------------------------------- + // Protected methods + // ----------------------------------------------- + + protected function getPrimaryCondition($key) { + // TODO: so rough. change. + $key = mysql_real_escape_string($key); + return "`" . self::FIELD_ID . "`='" . $key . "'"; + } + + protected function getTableRows() { + return array( self::FIELD_ID, + self::FIELD_USER, + self::FIELD_URL, + self::FIELD_NAME, + self::FIELD_DESCRIPTION, + self::FIELD_FAVORITE + ); + } + + protected function getTableRowTypes() { + return array( 'VARCHAR(25)', + 'VARCHAR(255)', + 'VARCHAR(255)', + 'VARCHAR(100)', + 'VARCHAR(500)', + 'BOOL'); + } + + protected function getTablePrimaryRow() { + return self::FIELD_ID; + } + + // ----------------------------------------------- + // Private methods + // ----------------------------------------------- + + /** + * Builds the condition using specific user name. + * + * @param $user + * @return string + */ + private function getUserCondition($user) { + return " `" . self::FIELD_USER . "`='$user'"; + } + +} \ No newline at end of file