powered by nequal
Home » Packages » Wozozo_WWW_YouTube » Source

Wozozo_WWW_YouTube / tags/0.0.7-stable-20110823013704/Wozozo/WWW/YouTube.php

Subversion URL: http://svn.openpear.org/Wozozo_WWW_YouTube/tags/0.0.7-stable-20110823013704/Wozozo/WWW/YouTube.php

Recent change

[2665] -- 2011-08-23 01:37:04
package released (0.0.7-stable) (@sasezaki)

<?php
require_once 'Wozozo/WWW/YouTube/VideoInfo.php';
 
class Wozozo_WWW_YouTube
{
    const PATH_INFO = 'http://www.youtube.com/get_video_info?video_id=%s';
    const BASE_URL = 'http://www.youtube.com/watch?v=';
 
    /**
     * @var Zend_Http_Client
     */
    protected $_httpClient;
 
    /**
     * @var array
     */
    protected $_config = array('prefer_fmt' => null,
                               'save' => 'GETCWD', //'GETCWD' will use getcwd();
                               'request_video_stream' => true, //output stream 
                               'response_video_cleanup' => true
                               );
    private $_clientStream;
 
    public function __construct($config = null)
    {
        if ($config) $this->setConfig($config);
    }
 
    public function setConfig($config = array())
    {
        if ($config instanceof Zend_Config) {
            $config = $config->toArray();
 
        } elseif (! is_array($config)) {
            throw new Exception('Array or Zend_Config object expected, got ' . gettype($config));
        }
 
        foreach ($config as $k => $v) {
            $this->_config[strtolower($k)] = $v;
        }
 
        return $this;
    }
 
    /**
     *
     * @param string|Zend_Uri $videoId
     * @param array|Zend_Config $config
     * @param $path
     * @return Wozozo_WWW_YouTube_VideoInfo
     */
    public static function download($videoId, $config = array())
    {
        $videoId = self::detectVideoId($videoId);
 
        $self = new self($config);
 
        $videoInfo = $self->getVideoInfo($videoId);
        $self->downloadByVideoInfo($videoInfo);
 
        return $videoInfo;
    }
 
    protected function _putVideo($response, Wozozo_WWW_YouTube_VideoInfo $videoInfo, $config)
    {
 
        if (is_string($config['save'])) {
            $path = $this->suggestSavePath($videoInfo);
        } else {
 
            return call_user_func($config['save'], $response, $videoInfo, $config);
        }
 
        $ret = @file_put_contents($path, $response->getRawBody());
        if ($ret === false) {
            throw new Exception('cannot write at' . $path);
        }
    }
 
    /**
     * request & get videoinfo
     *
     * @param string $videoId
     */
    public function getVideoInfo($videoId)
    {
        $client = $this->getHttpClient();
 
        $client->setUri(sprintf(self::PATH_INFO, $videoId));
        $response = $client->request();
 
        parse_str($response->getBody(), $parse);
 
        return new Wozozo_WWW_YouTube_VideoInfo($parse);
    }
 
    /**
     * Request video file
     *
     * @param Wozozo_WWW_YouTube_VideoInfo
     * @return Zend_Http_Response_Stream
     */
    public function requestVideo(Wozozo_WWW_YouTube_VideoInfo $videoInfo)
    {   
        // retrive url & save-file-path
        $url = $videoInfo->makeDownloadUrl($this->_config['prefer_fmt']);
 
        $client = $this->getHttpClient();
        $client->setUri($url);
 
        try {
            $this->_setupClientStream();
            $response = $client->request();
            $this->_restoreClientStream();
            $response->setCleanup($this->_config['response_video_cleanup']);
 
            return $response;
        } catch (Exception $e) {
            // ensure, restore HttpClient's origin stream
            $this->_restoreClientStream();
            throw $e;
        }
    }
 
    public function downloadByVideoInfo(Wozozo_WWW_YouTube_VideoInfo $videoInfo)
    {
        $response = $this->requestVideo($videoInfo);
 
        $this->_putVideo($response, $videoInfo, $this->_config);
    }
 
    private function _setupClientStream()
    {
        $this->_clientStream = $this->getHttpClient()->getStream();
        $this->getHttpClient()->setStream($this->_config['request_video_stream']);
    }
 
    private function _restoreClientStream()
    {
        $this->getHttpClient()->setStream($this->_clientStream);
    }
 
    public function getHttpClient()
    {
        if (!$this->_httpClient) {
            require_once 'Zend/Http/Client.php';
            $this->_httpClient = new Zend_Http_Client(null, array('useragent' => __CLASS__));
        }
 
        return $this->_httpClient;
    }
 
    public function setHttpClient(Zend_Http_Client $client)
    {
        $this->_httpClient = $client;
    }
 
    public function suggestSavePath($videoInfo)
    {
        $dir = $this->_config['save'];
        $fmt = $this->_config['prefer_fmt'];
        if ('GETCWD' ===  $dir) {
            $dir = getcwd();
        } else {
            if(!is_dir($dir)) {
                throw new InvalidArgumentException('Invalid dir'.$dir);
            }
        }
        $path = $dir . DIRECTORY_SEPARATOR . $videoInfo['video_id'] . self::detectSuffix($videoInfo->detectFmt($fmt));
 
        return $path;
    }
 
    /**
     * borrowed from WWW::YouTube::Download
     *
     * @see 
     * http://cpansearch.perl.org/src/XAICRON/WWW-YouTube-Download-0.13/lib/WWW/YouTube/Download.pm
     *
     * @param string 
     * @return string  
     */
    public static function detectSuffix($fmt)
    {
        switch ($fmt) {
            case '18' :
            case '22' :
            case '37' :
            case '38' :
                return '.mp4';
            case '17' :
                return '.3gp';
            case '43':
            case '44':
            case '45':
                return '.webm';
            default :
                return '.flv';
        }
    }
 
    /**
     * detect videoId
     *
     * @param string $var (url)
     * @return string|false
     */
    public static function detectVideoId($var)
    {
        if (is_string($var)) {
            if (!preg_match('#^h*(?:ttp\:\/\/)(.+\/watch\?v=.*)#', $var, $match)) {
                if (!preg_match('#^[A-Za-z0-9]+$#', $var)) {
                    throw new InvalidArgumentException('Invalid id '.$var);
                }
                return trim($var);
            }
            //uri
            require_once 'Zend/Uri.php';
            $var = Zend_Uri::factory('http://'.$match[1]);
        }
 
        if ($var instanceof Zend_Uri_Http) {
            $query = $var->getQueryAsArray();
            return $query['v'];
        } 
 
        return false;
    }
}