Location: PHPKode > scripts > Deviantart Feed > deviantart-feed/deviantart.php
<?php

/**
 * Scrapes a recent deviations feed together from deviantart.
 *
 * Uses a json formatted string from deviantart which works currently, however
 * any changes will most likley break this. Hopefully only the xsl would need to
 * be updated in such an event.
 *
 * GENERAL DISCLAIMER
 *
 * I am not personally affiliated with DeviantART in any way. Use of the
 * DeviantART website by its Terms Of Service. I am not responsible for the way
 * you use this script. The use of this script to scrape your DeviantART user
 * gallery may be in breach of your agreement with DeviantART.
 *
 * LICENSE
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 *
 * @author Stephen Ingram <hide@address.com>
 * @copyright Copyright (c) 2008, Stephen Ingram
 * @package deviantartfeed
 * @category deviantartfeed
 * @todo The title and date regex is quick and dirty, it could easily be tripped
 *       up.
 * @todo Investigate further what sort of output the DeviantART "DiFi" script
 *       will generate.
 */
class deviantartfeed
{

    /**
     * Location of config file
     *
     * If you move or rename the deviantart.ini file you must edit this path.
     *
     * @var string
     */
    const config_file = 'deviantart.ini';

    /**
     * Holds loaded config array
     *
     * @var array
     */
    public $conf;

    /**
     * Filesystem path to cache file.
     *
     * @var string
     */
    public $cache;



    /**
     * Constructor does all the work
     */
    public function __construct()
    {

        $this->conf = parse_ini_file(self::config_file, true);

        $this->cache = $this->conf['cache']['path']
            . $this->conf['cache']['file'];

        if (file_exists($this->cache)
            && filemtime($this->cache) > time() - 86400)
            return $this->output_cache();

        /**
         * Set url, broken into multiple lines for readability. Well...
         */
        $url = "http://{$this->conf[feed][user]}artist.deviantart.com/global/difi/"
            . "?c%5B%5D=Resources;htmlFromQuery;gallery%3A{$this->conf[feed][user]}"
            . "%20sort%3Atime,{$this->conf[feed][start]},{$this->conf[feed][request]}"
            . ",thumb150,artist%3A0&t=json";

        /**
         * Spoof user agent, not really necessary.
         */
        ini_set(
            'user_agent',
            'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.1)'
            );

        /**
         * Get json string
         */
        if (!$result = file_get_contents($url))
            return;

        /**
         * Decode json string
         */
        $result_object = json_decode($result);

        /**
         * Define xml file, includes attributes on channel that are used by the
         * php function calls.
         */
        $xml = "<channel
            imageurl=\"{$this->conf[imagecache][url]}\"
            imagecache=\"{$this->conf[imagecache][path]}\"
            >
            <title>{$this->conf[feed][user]}'s deviantART gallery</title>
            <link>http://{$this->conf[feed][user]}.deviantart.com</link>";

        /**
         * Add any additional channel elements as defined in ini
         */
        if (isset($this->conf['channel'])
            && !empty($this->conf['channel'])
            )
            foreach ($this->conf['channel'] as $name => $value)
                $xml .= "<{$name}>{$value}</{$name}>";

        $xml .= "<items>";

        /**
         * Add xml entry for each item in the response object.
         */
        foreach($result_object->DiFi->response->calls[0]->response->content->resources as $item)
            $xml .= '<item>' . $item[2] . '</item>';

        /**
         * Initialize the dom object and load the xml file from the string.
         */
        $dom = new DOMDocument;
        $dom->loadXML($xml . '</items></channel>');

        /**
         * Initialize the xsl dom object and load the xsl file form the
         * filesystem.
         */
        $xsl = new DOMDocument;
        $xsl->load($this->conf['xsl']['path']);

        /**
         * Initialize the XSLT processor and enable php function calls
         */
        $proc = new XSLTProcessor();
        $proc->registerPHPFunctions();

        /**
         * Import the xsl object
         */
        $proc->importStyleSheet($xsl);

        /**
         * Process the xml translation and save to the cache file.
         */
        file_put_contents($this->cache, $proc->transformToXML($dom));

        /**
         * Call deviantart::output_cahce() to send the rss feed to the user,
         * if enabled
         */
        return $this->output_cache();

    }



    /**
     * Return or send cache depenging on setting
     *
     * If not in cron mode sends the contents of the cache file to the user,
     * otherwise simply returns void.
     *
     * @return void
     */
    public function output_cache()
    {

        if($this->conf['general']['cron'])
            return;

/* or redirect to the feed.
        header('Location: '
            . $this->conf['general']['url']
            . $this->conf['cache']['url']
            . $this->conf['cache']['file']
            );
*/

        if (strpos($_SERVER['HTTP_USER_AGENT'], 'Mozilla')) {
            header('Content-type: text/xml');
        } else {
            header('Content-Type: application/rss+xml');
        }

        header('Last-Modified: ' . date('r', filemtime($this->cache)));

        echo file_get_contents($this->cache);

        return;

    }



    /**
     * Downloads a local cache of specified file.
     *
     * @param string $url
     * @param string $base URL base to apply to output URL
     * @param string $path Path base for local filesystem path.
     * @return string URL to local cache.
     */
    public static function xsl_make_local_cache($url, $base = '', $path = '')
    {

        ini_set(
            'user_agent',
            'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.1) Gecko/Firefox/3.0.1'
            );

        /**
         * Get file name
         */
        $file = substr($url, strrpos($url, '/') + 1);

        if (file_exists($path . $file))
            return $base . $file;

        file_put_contents($path . $file, file_get_contents($url));

        return $base . $file;

    }



    /**
     * Gets the artwork title from the proviced string
     *
     * @param string $string Vale of title attribute from input xml
     * @return string Artwork title
     */
    public static function xsl_get_title($string)
    {

        preg_match(
            '/(.*?) by/',
            $string,
            $title
            );

        return $title[1];

    }



    /**
     * Gets the artwork date in RFC 2822 format from the proviced string
     *
     * I'm assuming that deviantart records dates in UTC time, however I could
     * be wrong.
     *
     * @param string $string Vale of title attribute from input xml
     * @return string Artwork date
     */
    public static function xsl_get_date($string)
    {

        /**
         * I'm assuming that you can't have a , in your artork title.
         */
        preg_match(
            '/, (.*)/',
            $string,
            $date
            );

        date_default_timezone_set('UTC');

        return date('r', strtotime($date[1]));

    }

}

new deviantartfeed;
Return current item: Deviantart Feed