/** * DOCUMENT ME * @param mixed $width * @param mixed $height * @param mixed $resizeType * @param mixed $format * @param mixed $absolute * @param mixed $wmode * @param mixed $autoplay * @param array $options * @return mixed */ public function getEmbedCode($width, $height, $resizeType, $format = 'jpg', $absolute = false, $wmode = 'opaque', $autoplay = false, $options = array()) { if ($height === false) { // We need to scale the height. That requires knowing the true height if (!$this->height) { // Not known yet. This comes up when previewing a video with a service URL that we haven't saved yet if ($this->service_url) { $service = aMediaTools::getEmbedService($this->service_url); $thumbnail = $service->getThumbnail($service->getIdFromUrl($this->service_url)); if ($thumbnail) { $info = aImageConverter::getInfo($thumbnail); if (isset($info['width'])) { $this->width = $info['width']; $this->height = $info['height']; } } } } $height = floor($width * $this->height / $this->width + 0.5); } // Accessible alt title $title = htmlentities($this->getTitle(), ENT_COMPAT, 'UTF-8'); if ($this->getEmbeddable()) { if ($this->service_url) { $service = aMediaTools::getEmbedService($this->service_url); if (!$service) { // Most likely explanation: this service was configured, now it's not. // Don't crash return '<div>Video Service Not Available</div>'; } return $service->embed($service->getIdFromUrl($this->service_url), $width, $height, $title, $wmode, $autoplay); } elseif ($this->embed) { // Solution for non-YouTube videos based on a manually // provided thumbnail and embed code return str_replace(array('_TITLE_', '_WIDTH_', '_HEIGHT_'), array($title, $width, $height, $wmode), $this->embed); } else { throw new sfException('Media item without an embed code or a service url'); } } elseif ($this->getType() == 'image' || $this->getType() == 'pdf') { // Use named routing rule to ensure the desired result (and for speed) return "<img alt=\"{$title}\" width=\"{$width}\" height=\"{$height}\" src='" . htmlspecialchars($this->getImgSrcUrl($width, $height, $resizeType, $format, $absolute, $options)) . "' />"; } else { throw new Exception("Unknown media type in getEmbedCode: " . $this->getType() . " id is " . $this->id . " is new? " . $this->isNew()); } }
/** * DOCUMENT ME * @param mixed $arguments * @param mixed $options */ protected function execute($arguments = array(), $options = array()) { // We need a basic context so we can call helpers to format text $context = sfContext::createInstance($this->configuration); // initialize the database connection $databaseManager = new sfDatabaseManager($this->configuration); $connection = $databaseManager->getDatabase($options['connection'] ? $options['connection'] : null)->getConnection(); // PDO connection not so useful, get the doctrine one $conn = Doctrine_Manager::connection(); $accounts = Doctrine::getTable('aEmbedMediaAccount')->findAll(); foreach ($accounts as $a) { $perPage = 50; $service = aMediaTools::getEmbedService($a->service); if (!$service) { // An account for a service that has been deconfigured continue; } $total = null; $page = 1; $serviceUrls = array(); while (true) { $results = $service->browseUser($a->username, $page, $perPage); if ($results === false) { // We hit the rate limit, the account is bad, etc. Just // be tolerant and retry later. Would be nice to distinguish // these cases but it's not that hard to figure out an // account is gone break; } foreach ($results['results'] as $result) { $serviceUrls[] = $result['url']; } // We hit the end of the results for this user if (!count($results['results'])) { break; } $page++; } if (count($serviceUrls)) { $existingServiceUrls = Doctrine::getTable('aMediaItem')->createQuery('m')->select('m.service_url')->andWhereIn('m.service_url', $serviceUrls)->execute(array(), Doctrine::HYDRATE_SINGLE_SCALAR); } else { $existingServiceUrls = array(); } $existingServiceUrls = array_flip($existingServiceUrls); foreach ($serviceUrls as $serviceUrl) { if (!isset($existingServiceUrls[$serviceUrl])) { // If Doctrine becomes a performance problem I could use PDO // and set lucene_dirty to let that clean itself up later $id = $service->getIdFromUrl($serviceUrl); $info = $service->getInfo($id); if (!$info) { // We are not actually allowed meaningful access to this video. Password protected for example continue; } $item = new aMediaItem(); $item->setTitle($info['title']); // We want tags to be lower case, and slashes break routes in most server configs. $info['tags'] = str_replace('/', '-', aString::strtolower($info['tags'])); $item->setTags($info['tags']); $item->setDescription(aHtml::textToHtml($info['description'])); $item->setCredit($info['credit']); $item->setServiceUrl($info['url']); $item->setType($service->getType()); // The dance is this: get the thumbnail if there is one; // call preSaveFile to learn the width, height and format // before saving; save; and then saveFile to copy it to a // filename based on the slug, which is unknown until after save $thumbnail = $service->getThumbnail($id); if ($thumbnail) { // Grab a local copy of the thumbnail, and get the pain // over with all at once in a predictable way if // the service provider fails to give it to us. $thumbnailCopy = aFiles::getTemporaryFilename(); if (copy($thumbnail, $thumbnailCopy)) { $item->preSaveFile($thumbnailCopy); } } $item->save(); if ($thumbnail) { $item->saveFile($thumbnailCopy); } $item->free(); } } } }
/** * Finds or adds a video without the overhead of a proper Doctrine save. * @param array $info * @return mixed */ protected function findOrAddVideo($info) { $mediaId = null; $slug = null; if (!isset($info['title'])) { $info['title'] = 'Imported video'; } $slug = aTools::slugify(!empty($info['title']) ? $info['title'] : (!empty($info['service_url']) ? $info['service_url'] : md5($info['embed']))); $result = $this->sql->query('SELECT id FROM a_media_item WHERE slug = :slug', array('slug' => $slug)); if (isset($result[0]['id'])) { $mediaId = $result[0]['id']; } else { $mediaItem = new aMediaItem(); foreach ($info as $key => $value) { if ($key !== 'tags') { $mediaItem[$key] = $value; } } if (empty($mediaItem['title'])) { $mediaItem->setTitle($slug); } else { $mediaItem->setTitle($info['title']); } $mediaItem->setSlug($slug); $mediaItem->setType('video'); if ($mediaItem->service_url) { $service = aMediaTools::getEmbedService($mediaItem->service_url); $id = $service->getIdFromUrl($mediaItem->service_url); if ($service->supports('thumbnail')) { $filename = $service->getThumbnail($id); if ($filename) { // saveFile can't handle a nonlocal file directly, so // copy to a temporary file first $bad = isset($this->failedMedia[$filename]); if (!$bad) { $tmpFile = aFiles::getTemporaryFilename(); try { if (!copy($filename, $tmpFile)) { throw new sfException(sprintf('Could not copy file: %s', $src)); } if (!$mediaItem->saveFile($tmpFile)) { throw new sfException(sprintf('Could not save file: %s', $src)); } } catch (Exception $e) { $this->failedMedia[$filename] = true; } unlink($tmpFile); } } } } $this->sql->fastSaveMediaItem($mediaItem); if (count($info['tags'])) { $this->sql->fastSaveTags('aMediaItem', $mediaItem->id, $info['tags']); } $mediaId = $mediaItem->id; $mediaItem->free(true); } return $mediaId; }
/** * * preValidateEmbed * @param $value * @return array * @author Thomas Boutell * / */ public function classifyEmbed($value) { // If it is a URL or embed code recognized by one of the services we support, use that service $service = aMediaTools::getEmbedService($value); if ($service) { $id = $service->getIdFromUrl($value); if (!$id) { // Not every service considers URLs and embed codes interchangeable $id = $service->getIdFromEmbed($value); } $serviceInfo = $service->getInfo($id); if (!$serviceInfo) { $this->classifyEmbedResult = array('ok' => false, 'error' => 'That video does not exist or you cannot access it.'); return $this->classifyEmbedResult; } $thumbnail = $service->getThumbnail($id); $info = aImageConverter::getInfo($thumbnail); if (!isset($info['width'])) { $this->classifyEmbedResult = array('ok' => false, 'error' => 'That video exists but the service provider does not allow you to embed it.'); return $this->classifyEmbedResult; } $this->classifyEmbedResult = array('ok' => true, 'thumbnail' => $thumbnail, 'serviceInfo' => $serviceInfo, 'embed' => $service->embed($id, $info['width'], $info['height']), 'width' => $info['width'], 'height' => $info['height'], 'format' => $info['format'], 'serviceUrl' => $service->getUrlFromId($id)); return $this->classifyEmbedResult; } // Don't let this become a way to embed arbitrary HTML $value = trim(strip_tags($value, "<embed><object><param><applet><iframe>")); // Kill any text outside of tags if (preg_match_all("/<.*?>/", $value, $matches)) { $value = implode("", $matches[0]); } else { $value = ''; } if (!strlen($value)) { $this->classifyEmbedResult = array('ok' => false, 'error' => 'A valid embed code or recognized media service URL is required.'); return $this->classifyEmbedResult; } // For existing objects the embed code will already be parameterized, in that situation // we don't try (and fail) to extract the dimensions again if (strpos($value, '_WIDTH_') === false) { // If the width or height is not available, we can't process it correctly if (!preg_match("/width\\s*=\\s*([\"'])(\\d+)\\1/i", $value) || !preg_match("/height\\s*=\\s*([\"'])(\\d+)\\1/i", $value, $matches)) { $this->classifyEmbedResult = array('ok' => false, 'error' => 'No width and height in embed code'); return $this->classifyEmbedResult; } if (preg_match("/width\\s*=\\s*([\"'])(\\d+)\\1/i", $value, $matches)) { $result['width'] = $matches[2]; } if (preg_match("/height\\s*=\\s*([\"'])(\\d+)\\1/i", $value, $matches)) { $result['height'] = $matches[2]; } } else { $result['width'] = $this->getObject()->width; $result['height'] = $this->getObject()->height; } // Put placeholders in the embed/applet/object tags $value = preg_replace(array("/width\\s*=\\s*([\"'])\\d+%?\\1/i", "/height\\s*=\\s*([\"'])\\d+%?\\1/i", "/alt\\s*\\s*([\"']).*?\\1/i"), array("width=\"_WIDTH_\"", "height=\"_HEIGHT_\"", "alt=\"_TITLE_\""), $value); $result['ok'] = true; $result['embed'] = $value; $this->classifyEmbedResult = $result; return $this->classifyEmbedResult; }
/** * DOCUMENT ME * @param sfRequest $request * @return mixed */ public function executeLinkPreviewAccount(sfRequest $request) { $this->forward404Unless($this->isAdmin()); $params = $request->getParameter('a_embed_media_account'); $service = $params['service']; $this->username = $params['username']; $this->service = aMediaTools::getEmbedService($service); $this->forward404Unless($this->service); $info = $this->service->getUserInfo($this->username); if (!$info) { return 'Error'; } $this->name = $info['name']; $this->description = $info['description']; // Grab their three newest videos $this->results = $this->service->browseUser($this->username, 1, 3); }