Esempio n. 1
0
 /**
  * Rock the Symfony cache to avoid fetching the same external URL over and over
  * These defaults are safe and boring and way faster than bashing on other servers.
  * But here's a tip. If you don't have APC enabled your site is probably running very,
  * very slowly, so fix that. And then do this for even better speed:
  * 
  * a:
  * feed:
  * cache_class: sfAPCCache
  * cache_options: { }
  * @param mixed $url
  * @param mixed $interval
  * @return mixed
  */
 public static function fetchCachedFeed($url, $interval = 300)
 {
     $cacheClass = sfConfig::get('app_a_feed_cache_class', 'sfFileCache');
     $cache = new $cacheClass(sfConfig::get('app_a_feed_cache_options', array('cache_dir' => aFiles::getWritableDataFolder(array('a_feed_cache')))));
     $key = 'apostrophe:feed:' . $url;
     $feed = $cache->get($key, false);
     if ($feed === 'invalid') {
         return false;
     } else {
         if ($feed !== false) {
             // sfFeed is designed to serialize well
             $feed = unserialize($feed);
         }
     }
     if (!$feed) {
         try {
             // We now always use the fopen adapter and specify a time limit, which is configurable.
             // Francois' comments about fopen being slow are probably dated, the stream wrappers are
             // quite good in modern PHP and in any case Apostrophe uses them consistently elsewhere
             $options = array('adapter' => 'sfFopenAdapter', 'adapter_options' => array('timeout' => sfConfig::get('app_a_feed_timeout', 30)));
             $feed = sfFeedPeer::createFromWeb($url, $options);
             $cache->set($key, serialize($feed), $interval);
         } catch (Exception $e) {
             // Cache the fact that the feed is invalid for 60 seconds so we don't
             // beat the daylights out of a dead feed
             $cache->set($key, 'invalid', 60);
             return false;
         }
     }
     return $feed;
 }
Esempio n. 2
0
 public static function fetchCachedFeed($url, $interval = 300)
 {
     $cacheClass = sfConfig::get('app_a_feed_cache_class', 'sfFileCache');
     $cache = new $cacheClass(sfConfig::get('app_a_feed_cache_options', array('cache_dir' => aFiles::getWritableDataFolder(array('a_feed_cache')))));
     $key = 'apostrophe:feed:' . $url;
     $feed = $cache->get($key, false);
     if ($feed === 'invalid') {
         return false;
     } else {
         if ($feed !== false) {
             // sfFeed is designed to serialize well
             $feed = unserialize($feed);
         }
     }
     if (!$feed) {
         try {
             $feed = sfFeedPeer::createFromWeb($url);
             $cache->set($key, serialize($feed), $interval);
         } catch (Exception $e) {
             // Cache the fact that the feed is invalid for 60 seconds so we don't
             // beat the daylights out of a dead feed
             $cache->set($key, 'invalid', 60);
             return false;
         }
     }
     return $feed;
 }
Esempio n. 3
0
 /**
  * command.post_command
  * @param sfEvent $event
  */
 public static function listenToCommandPostCommandEvent(sfEvent $event)
 {
     if (aToolkitEvents::$once) {
         return;
     }
     aToolkitEvents::$once = true;
     $task = $event->getSubject();
     if ($task->getFullName() === 'project:permissions') {
         $writable = aFiles::getWritableDataFolder();
         $task->getFilesystem()->chmod($writable, 0777);
         $dirFinder = sfFinder::type('dir');
         $fileFinder = sfFinder::type('file');
         $task->getFilesystem()->chmod($dirFinder->in($writable), 0777);
         $task->getFilesystem()->chmod($fileFinder->in($writable), 0666);
     }
     if ($task->getFullName() === 'cache:clear') {
         aAssets::clearAssetCache($task->getFilesystem());
         // Clear the page cache on symfony cc
         if (sfConfig::get('app_a_page_cache_enabled', false)) {
             echo "Clearing Apostrophe page cache\n";
             $cache = aCacheFilter::getCache();
             $cache->clean();
         } else {
             // Cache not enabled for this environment. Too many tasks
             // invoke symfony cc with no environment, so let's not print
             // anything needlessly worrying here
         }
     }
 }
Esempio n. 4
0
 /**
  * DOCUMENT ME
  * @param mixed $args
  * @param mixed $options
  */
 protected function execute($args = array(), $options = array())
 {
     $conn = 'doctrine';
     $params = sfSyncContentTools::shellDatabaseParams(sfSyncContentTools::getDatabaseParams($this->configuration, $conn));
     $dataDir = aFiles::getWritableDataFolder();
     $uploadDir = aFiles::getUploadFolder();
     // $dataDir will be a_writable, sf_data_dir is its parent, so we can put things there and
     // trust that they are not crushed by the unzip
     $dataZip = sfConfig::get('sf_data_dir') . '/apostrophedemo-awritable.zip';
     if (!copy('http://content.apostrophenow.com/uploads/apostrophedemo-awritable.zip', $dataZip)) {
         throw new sfException("Unable to copy http://content.apostrophenow.com/uploads/apostrophedemo-awritable.zip to {$dataZip}");
     }
     $uploadZip = sfConfig::get('sf_data_dir') . '/apostrophedemo-uploads.zip';
     if (!copy("http://content.apostrophenow.com/uploads/apostrophedemo-uploads.zip", $uploadZip)) {
         throw new sfException('Unable to copy http://content.apostrophenow.com/uploads/apostrophedemo-uploads.zip to $dataZip');
     }
     $this->unzip($dataDir, $dataZip, $options);
     $this->unzip($uploadDir, $uploadZip, $options);
     // Yes, you need to have mysql to use this feature.
     // However you can set app_syncContent_mysql to
     // the path of your mysql utility if it is called something
     // else or not in the PATH
     $mysql = sfConfig::get('app_syncContent_mysql', 'mysql');
     system(escapeshellarg($mysql) . " {$params} < " . escapeshellarg($dataDir . '/ademocontent.sql'), $result);
     if ($result != 0) {
         throw new sfException("mysql failed. Maybe you don't have it in your PATH");
     }
     // Undo the little dance we did to send the demo password across without forcing the use
     // of a known password salt or a particular encryption scheme on the receiving site.
     // The demo password is no secret, but new passwords set later should be, so we don't
     // want to force a salt when generating the demo dump. See aSyncActions for details
     if ($options['verbose']) {
         echo "Postprocessing users\n";
     }
     $users = Doctrine::getTable('sfGuardUser')->findAll();
     foreach ($users as $user) {
         // If there is a salt, and no password, it's really a hint to turn the cleartext password
         // into a proper one and establish a salt
         if (!strlen($user->getPassword())) {
             $demoPassword = $user->getSalt();
             if (strlen($demoPassword)) {
                 $user->setSalt('');
                 $user->setPassword($demoPassword);
                 $user->save();
             }
         }
     }
     if ($options['verbose']) {
         echo "Content loaded.\n";
     }
     system('./symfony apostrophe:rebuild-search-index', $result);
     if ($result != 0) {
         throw new sfException('Problem executing apostrophe:rebuild-search-index task.');
     }
 }
Esempio n. 5
0
 public static function listenToCommandPostCommandEvent(sfEvent $event)
 {
     $task = $event->getSubject();
     if ($task->getFullName() === 'project:permissions') {
         $writable = aFiles::getWritableDataFolder();
         $task->getFilesystem()->chmod($writable, 0777);
         $dirFinder = sfFinder::type('dir');
         $fileFinder = sfFinder::type('file');
         $task->getFilesystem()->chmod($dirFinder->in($writable), 0777);
         $task->getFilesystem()->chmod($fileFinder->in($writable), 0666);
     }
 }
Esempio n. 6
0
    /**
     * DOCUMENT ME
     * @param mixed $arguments
     * @param mixed $options
     */
    protected function execute($arguments = array(), $options = array())
    {
        $scriptFile = aFiles::getTemporaryFilename();
        $out = fopen($scriptFile, "w");
        $server = $arguments['server'];
        $data = parse_ini_file($this->configuration->getRootDir() . '/config/properties.ini', true);
        if (!isset($data[$server])) {
            throw new sfException("{$server} does not exist in config/properties.ini. Examples: staging, production\n");
        }
        $data = $data[$server];
        $cmd = "ssh ";
        if (isset($data['port'])) {
            $cmd .= "-p " . $data['port'];
        }
        if (isset($data['user'])) {
            $cmd .= " -l " . $data['user'];
        }
        $cmd .= " " . $data['host'];
        $dir = $data['dir'];
        $user = $data['user'];
        $host = $data['host'];
        $escapedDir = escapeshellarg($dir);
        $cd = escapeshellcmd("cd {$escapedDir}");
        fwrite($out, <<<EOM
spawn {$cmd}
stty -echo
expect password:
send_user -- "Password for {$user}@{$host}: "
expect_user -re "(.*)\\n"
send_user "\\n"
stty echo
set password \$expect_out(1,string)
send "\$password\\n"
expect "\\\\\$"
send "{$cd}\\n"
interact 
EOM
);
        passthru("expect {$scriptFile}");
        unlink($scriptFile);
    }
Esempio n. 7
0
 public function executeEditVideo(sfRequest $request)
 {
     $this->forward404Unless(aMediaTools::userHasUploadPrivilege());
     $item = null;
     $this->slug = false;
     if ($request->hasParameter('slug')) {
         $item = $this->getItem();
         $this->slug = $item->getSlug();
     }
     if ($item) {
         $this->forward404Unless($item->userHasPrivilege('edit'));
     }
     $this->item = $item;
     $subclass = 'aMediaVideoYoutubeForm';
     $embed = false;
     $parameters = $request->getParameter('a_media_item');
     if (aMediaTools::getOption('embed_codes') && ($item && strlen($item->embed) || isset($parameters['embed']))) {
         $subclass = 'aMediaVideoEmbedForm';
         $embed = true;
     }
     $this->form = new $subclass($item);
     if ($parameters) {
         $files = $request->getFiles('a_media_item');
         $this->form->bind($parameters, $files);
         do {
             // first_pass forces the user to interact with the form
             // at least once. Used when we're coming from a
             // YouTube search and we already technically have a
             // valid form but want the user to think about whether
             // the title is adequate and perhaps add a description,
             // tags, etc.
             if ($this->hasRequestParameter('first_pass') || !$this->form->isValid()) {
                 break;
             }
             // TODO: this is pretty awful factoring, I should have separate actions
             // and migrate more of this code into the model layer
             if ($embed) {
                 $embed = $this->form->getValue("embed");
                 $thumbnail = $this->form->getValue('thumbnail');
                 // The base implementation for saving files gets confused when
                 // $file is not set, a situation that our code tolerates as useful
                 // because if you're updating a record containing an image you
                 // often don't need to submit a new one.
                 unset($this->form['thumbnail']);
                 $object = $this->form->getObject();
                 if ($thumbnail) {
                     $object->preSaveImage($thumbnail->getTempName());
                 }
                 $this->form->save();
                 if ($thumbnail) {
                     $object->saveImage($thumbnail->getTempName());
                 }
             } else {
                 $url = $this->form->getValue("service_url");
                 // TODO: migrate this into the model and a
                 // YouTube-specific support class
                 if (!preg_match("/youtube.com.*\\?.*v=([\\w\\-\\+]+)/", $url, $matches)) {
                     $this->serviceError = true;
                     break;
                 }
                 // YouTube thumbnails are always JPEG
                 $format = 'jpg';
                 $videoid = $matches[1];
                 $feed = "http://gdata.youtube.com/feeds/api/videos/{$videoid}";
                 $entry = simplexml_load_file($feed);
                 // get nodes in media: namespace for media information
                 $media = $entry->children('http://search.yahoo.com/mrss/');
                 // get a more canonical video player URL
                 $attrs = $media->group->player->attributes();
                 $canonicalUrl = $attrs['url'];
                 // get biggest video thumbnail
                 foreach ($media->group->thumbnail as $thumbnail) {
                     $attrs = $thumbnail->attributes();
                     if (!isset($widest) || $attrs['width'] + 0 > $widest['width'] + 0) {
                         $widest = $attrs;
                     }
                 }
                 // The YouTube API doesn't report the original width and height of
                 // the video stream, so we use the largest thumbnail, which in practice
                 // is the same thing on YouTube.
                 if (isset($widest)) {
                     $thumbnail = $widest['url'];
                     // Turn them into actual numbers instead of weird XML wrapper things
                     $width = $widest['width'] + 0;
                     $height = $widest['height'] + 0;
                 }
                 if (!isset($thumbnail)) {
                     $this->serviceError = true;
                     break;
                 }
                 // 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)) {
                     $this->serviceError = true;
                     break;
                 }
                 $object = $this->form->getObject();
                 $new = !$object->getId();
                 $object->preSaveImage($thumbnailCopy);
                 $object->setServiceUrl($url);
                 $this->form->save();
                 $object->saveImage($thumbnailCopy);
                 unlink($thumbnailCopy);
             }
             return $this->redirect("aMedia/resumeWithPage");
         } while (false);
     }
 }
 /**
  * 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();
             }
         }
     }
 }
 /**
  * @param  string $name        The element name
  * @param  string $value       The value displayed in this widget
  *                             (i.e. the browser-side filename submitted
  *                             on a previous partially successful
  *                             validation of this form)
  * @param  array  $attributes  An array of HTML attributes to be merged with the default HTML attributes
  * @param  array  $errors      An array of errors for the field
  *
  * @return string An HTML tag string
  *
  * @see sfWidgetForm
  */
 public function render($name, $value = null, $attributes = array(), $errors = array())
 {
     $exists = false;
     if (isset($value['persistid']) && strlen($value['persistid'])) {
         $persistid = $value['persistid'];
         $info = aValidatorFilePersistent::getFileInfo($persistid);
         if ($info) {
             $exists = true;
         }
     } else {
         // One implementation, not two (to inevitably drift apart)
         $persistid = aGuid::generate();
     }
     $result = '';
     // hasOption just verifies that the option is valid, it doesn't check what,
     // if anything, was passed. Thanks to Lucjan Wilczewski
     $preview = $this->hasOption('image-preview') ? $this->getOption('image-preview') : false;
     $defaultPreview = $this->hasOption('default-preview') ? $this->getOption('default-preview') : false;
     if ($exists) {
         $defaultPreview = false;
     }
     if ($exists || $defaultPreview) {
         if ($preview) {
             // Note change of key
             $urlStem = sfConfig::get('app_aPersistentFileUpload_preview_url', '/uploads/uploaded_image_preview');
             // This is the corresponding directory path. You have to override one
             // if you override the other. You override this one by setting
             // app_aToolkit_upload_uploaded_image_preview_dir
             $dir = aFiles::getUploadFolder("uploaded_image_preview");
             // While we're here age off stale previews
             aValidatorFilePersistent::removeOldFiles($dir);
             $imagePreview = $this->getOption('image-preview');
             if ($exists) {
                 $source = $info['tmp_name'];
             } else {
                 $source = $defaultPreview;
             }
             $info = aImageConverter::getInfo($source);
             if ($info) {
                 $iwidth = $info['width'];
                 $height = $info['height'];
                 // This is safe - based on sniffed file contents and not a user supplied extension
                 $format = $info['format'];
                 list($iwidth, $iheight) = getimagesize($source);
                 $dimensions = aDimensions::constrain($iwidth, $iheight, $format, $imagePreview);
                 // A simple filename reveals less
                 $imagename = "{$persistid}.{$format}";
                 $url = "{$urlStem}/{$imagename}";
                 $output = "{$dir}/{$imagename}";
                 if (isset($info['newfile']) && $info['newfile'] || !file_exists($output)) {
                     if ($imagePreview['resizeType'] === 'c') {
                         $method = 'cropOriginal';
                     } else {
                         $method = 'scaleToFit';
                     }
                     sfContext::getInstance()->getLogger()->info("YY calling converter method {$method} width " . $dimensions['width'] . ' height ' . $dimensions['height']);
                     aImageConverter::$method($source, $output, $dimensions['width'], $dimensions['height']);
                     sfContext::getInstance()->getLogger()->info("YY after converter");
                 }
             }
             if (isset($imagePreview['markup'])) {
                 $markup = $imagePreview['markup'];
             } else {
                 $markup = '<img src="%s" />';
             }
             $result .= sprintf($markup, $url);
         }
         $result .= $this->getOption('existing-html');
     }
     return $result . $this->renderTag('input', array_merge(array('type' => $this->getOption('type'), 'name' => $name . '[newfile]'), $attributes)) . $this->renderTag('input', array('type' => 'hidden', 'name' => $name . '[persistid]', 'value' => $persistid));
 }
Esempio n. 10
0
function _a_get_assets_body($type, $assets)
{
    $gzip = sfConfig::get('app_a_minify_gzip', false);
    sfConfig::set('symfony.asset.' . $type . '_included', true);
    $html = '';
    // We need our own copy of the trivial case here because we rewrote the asset list
    // for stylesheets after LESS compilation, and there is no way to
    // reset the list in the response object
    if (!sfConfig::get('app_a_minify', false)) {
        // This branch is seen only for CSS, because javascript calls the original Symfony
        // functionality when minify is off
        foreach ($assets as $file => $options) {
            $html .= stylesheet_tag($file, $options);
        }
        return $html;
    }
    $sets = array();
    foreach ($assets as $file => $options) {
        if (preg_match('/^http(s)?:/', $file) || isset($options['data-minify']) && $options['data-minify'] === 0) {
            // Nonlocal URL or minify was explicitly shut off.
            // Don't get cute with it, otherwise things
            // like Addthis and ckeditor don't work
            if ($type === 'stylesheets') {
                $html .= stylesheet_tag($file, $options);
            } else {
                $html .= javascript_include_tag($file, $options);
            }
            continue;
        }
        /*
         *
         * Guts borrowed from stylesheet_tag and javascript_tag. We still do a tag if it's
         * a conditional stylesheet
         *
         */
        $absolute = false;
        if (isset($options['absolute']) && $options['absolute']) {
            unset($options['absolute']);
            $absolute = true;
        }
        $condition = null;
        if (isset($options['condition'])) {
            $condition = $options['condition'];
            unset($options['condition']);
        }
        if (!isset($options['raw_name'])) {
            if ($type === 'stylesheets') {
                $file = stylesheet_path($file, $absolute);
            } else {
                $file = javascript_path($file, $absolute);
            }
        } else {
            unset($options['raw_name']);
        }
        if (is_null($options)) {
            $options = array();
        }
        if ($type === 'stylesheets') {
            $options = array_merge(array('rel' => 'stylesheet', 'type' => 'text/css', 'media' => 'screen', 'href' => $file), $options);
        } else {
            $options = array_merge(array('type' => 'text/javascript', 'src' => $file), $options);
        }
        if (null !== $condition) {
            $tag = tag('link', $options);
            $tag = comment_as_conditional($condition, $tag);
            $html .= $tag . "\n";
        } else {
            unset($options['href'], $options['src']);
            $optionGroupKey = json_encode($options);
            $set[$optionGroupKey][] = $file;
        }
        // echo($file);
        // $html .= "<style>\n";
        // $html .= file_get_contents(sfConfig::get('sf_web_dir') . '/' . $file);
        // $html .= "</style>\n";
    }
    // CSS files with the same options grouped together to be loaded together
    foreach ($set as $optionsJson => $files) {
        $groupFilename = aAssets::getGroupFilename($files);
        $groupFilename .= $type === 'stylesheets' ? '.css' : '.js';
        if ($gzip) {
            $groupFilename .= 'gz';
        }
        $dir = aFiles::getUploadFolder(array('asset-cache'));
        if (!file_exists($dir . '/' . $groupFilename)) {
            $content = '';
            foreach ($files as $file) {
                $path = null;
                if (sfConfig::get('app_a_stylesheet_cache_http', false)) {
                    $url = sfContext::getRequest()->getUriPrefix() . $file;
                    $fileContent = file_get_contents($url);
                } else {
                    $path = sfConfig::get('sf_web_dir') . $file;
                    $fileContent = file_get_contents($path);
                }
                if ($type === 'stylesheets') {
                    $options = array();
                    if (!is_null($path)) {
                        // Rewrite relative URLs in CSS files.
                        // This trick is available only when we don't insist on
                        // pulling our CSS files via http rather than the filesystem
                        // dirname would resolve symbolic links, we don't want that
                        $fdir = preg_replace('/\\/[^\\/]*$/', '', $path);
                        $options['currentDir'] = $fdir;
                        $options['docRoot'] = sfConfig::get('sf_web_dir');
                    }
                    if (sfConfig::get('app_a_minify', false)) {
                        $fileContent = Minify_CSS::minify($fileContent, $options);
                    }
                } else {
                    // Trailing carriage return makes behavior more consistent with
                    // JavaScript's behavior when loading separate files. For instance,
                    // a missing trailing semicolon should be tolerated to the same
                    // degree it would be with separate files. The minifier is not
                    // a lint tool and should not surprise you with breakage
                    $fileContent = JSMin::minify($fileContent) . "\n";
                }
                $content .= $fileContent;
            }
            if ($gzip) {
                _gz_file_put_contents($dir . '/' . $groupFilename . '.tmp', $content);
            } else {
                file_put_contents($dir . '/' . $groupFilename . '.tmp', $content);
            }
            @rename($dir . '/' . $groupFilename . '.tmp', $dir . '/' . $groupFilename);
        }
        $options = json_decode($optionsJson, true);
        // Use stylesheet_path and javascript_path so we can respect relative_root_dir
        if ($type === 'stylesheets') {
            $options['href'] = stylesheet_path(sfConfig::get('app_a_assetCacheUrl', '/uploads/asset-cache') . '/' . $groupFilename);
            $html .= tag('link', $options);
        } else {
            $options['src'] = javascript_path(sfConfig::get('app_a_assetCacheUrl', '/uploads/asset-cache') . '/' . $groupFilename);
            $html .= content_tag('script', '', $options);
        }
    }
    return $html;
}
Esempio n. 11
0
 public static function getLuceneIndexFile(Doctrine_Table $table)
 {
     return aFiles::getWritableDataFolder(array('zend_indexes')) . DIRECTORY_SEPARATOR . $table->getOption('name') . '.' . sfConfig::get('sf_environment') . '.index';
 }
Esempio n. 12
0
 /**
  * Lock names must be \w+
  * @param mixed $name
  */
 public static function lock($name)
 {
     $dir = aFiles::getWritableDataFolder(array('a', 'locks'));
     if (!preg_match('/^\\w+$/', $name)) {
         throw new sfException("Lock name is empty or contains non-word characters");
     }
     $file = "{$dir}/{$name}.lck";
     while (true) {
         $fp = fopen($file, 'a');
         if ($fp) {
             if (flock($fp, LOCK_EX)) {
                 break;
             }
         }
         sleep(1);
     }
     flock($fp, LOCK_EX);
     aTools::$locks[] = $fp;
 }
Esempio n. 13
0
 /**
  * DOCUMENT ME
  * @return mixed
  */
 public static function getHintCache()
 {
     $cacheClass = sfConfig::get('app_a_hint_cache_class', 'sfFileCache');
     $cache = new $cacheClass(sfConfig::get('app_a_hint_cache_options', array('cache_dir' => aFiles::getWritableDataFolder(array('a_hint_cache')))));
     return $cache;
 }
Esempio n. 14
0
 /**
  * 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;
 }
Esempio n. 15
0
 /**
  * DOCUMENT ME
  * @param sfWebRequest $request
  * @return mixed
  */
 public function executeEditVideo(sfWebRequest $request)
 {
     $this->forward404Unless(aMediaTools::userHasUploadPrivilege());
     $item = null;
     $this->slug = false;
     $this->popularTags = PluginTagTable::getPopulars(null, array('sort_by_popularity' => true), false, 10);
     if (sfConfig::get('app_a_all_tags', true)) {
         $this->allTags = PluginTagTable::getAllTagNameWithCount();
     } else {
         $this->allTags = array();
     }
     if ($request->hasParameter('slug')) {
         $item = $this->getItem();
         $this->slug = $item->getSlug();
     }
     if ($item) {
         $this->forward404Unless($item->userHasPrivilege('edit'));
     }
     $this->item = $item;
     $embed = false;
     $parameters = $request->getParameter('a_media_item');
     if ($parameters) {
         $files = $request->getFiles('a_media_item');
         $this->form = new aMediaVideoForm($item);
         if (isset($parameters['embed'])) {
             // We need to do some prevalidation of the embed code so we can prestuff the
             // file, title, tags and description widgets
             $result = $this->form->classifyEmbed($parameters['embed']);
             if (isset($result['thumbnail'])) {
                 $thumbnail = $result['thumbnail'];
                 if (!isset($parameters['title']) && !isset($parameters['tags']) && !isset($parameters['description']) && !isset($parameters['credit'])) {
                     $parameters['title'] = $result['serviceInfo']['title'];
                     // We want tags to be lower case, and slashes break routes in most server configs.
                     $parameters['tags'] = str_replace('/', '-', aString::strtolower($result['serviceInfo']['tags']));
                     $parameters['description'] = aHtml::textToHtml($result['serviceInfo']['description']);
                     $parameters['credit'] = $result['serviceInfo']['credit'];
                 }
             }
         }
         // On the first pass with a youtube video we just make the service's thumbnail the
         // default thumbnail. We don't force them to use it. This allows more code reuse
         // (Moving this after the bind is necessary to keep it from being overwritten)
         if (isset($thumbnail)) {
             // OMG file widgets can't have defaults! Ah, but our persistent file widget can
             $tmpFile = aFiles::getTemporaryFilename();
             file_put_contents($tmpFile, file_get_contents($thumbnail));
             $vfp = new aValidatorFilePersistent();
             $guid = aGuid::generate();
             $vfp->clean(array('newfile' => array('tmp_name' => $tmpFile), 'persistid' => $guid));
             // You can't mess about with widget defaults after a bind, but you
             // *can* tweak the array you're about to bind with
             $parameters['file']['persistid'] = $guid;
         }
         $this->form->bind($parameters, $files);
         do {
             // first_pass forces the user to interact with the form
             // at least once. Used when we're coming from a
             // YouTube search and we already technically have a
             // valid form but want the user to think about whether
             // the title is adequate and perhaps add a description,
             // tags, etc.
             if ($this->hasRequestParameter('first_pass') || !$this->form->isValid()) {
                 break;
             }
             $thumbnail = $this->form->getValue('file');
             // The base implementation for saving files gets confused when
             // $file is not set, a situation that our code tolerates as useful
             // because if you're updating a record containing an image you
             // often don't need to submit a new one.
             unset($this->form['file']);
             $object = $this->form->getObject();
             if ($thumbnail) {
                 $object->preSaveFile($thumbnail->getTempName());
             }
             $this->form->save();
             if ($thumbnail) {
                 $object->saveFile($thumbnail->getTempName());
             }
             return $this->redirect("aMedia/resumeWithPage");
         } while (false);
     }
 }
 /**
  * DOCUMENT ME
  * @param mixed $value
  * @param mixed $imagePreview
  * @return mixed
  */
 public function getPreviewUrl($value, $imagePreview = array())
 {
     list($exists, $persistid, $extension) = $this->getExistsPersistidAndExtension($value);
     // hasOption just verifies that the option is valid, it doesn't check what,
     // if anything, was passed. Thanks to Lucjan Wilczewski
     $defaultPreview = $this->hasOption('default-preview') ? $this->getOption('default-preview') : false;
     if ($exists) {
         $defaultPreview = false;
     }
     if ($exists || $defaultPreview) {
         // Note change of key
         $urlStem = sfConfig::get('app_aPersistentFileUpload_preview_url', '/uploads/uploaded_image_preview');
         $urlStem = sfContext::getInstance()->getRequest()->getRelativeUrlRoot() . $urlStem;
         // This is the corresponding directory path. You have to override one
         // if you override the other. You override this one by setting
         // app_aToolkit_upload_uploaded_image_preview_dir
         $dir = aFiles::getUploadFolder("uploaded_image_preview");
         // While we're here age off stale previews
         aValidatorFilePersistent::removeOldFiles($dir);
         if ($exists) {
             $info = aValidatorFilePersistent::getFileInfo($persistid);
             $source = $info['tmp_name'];
         } else {
             $source = $defaultPreview;
         }
         $info = aImageConverter::getInfo($source, array('format-only' => true));
         $previewable = false;
         if ($info && in_array($info['format'], array('jpg', 'png', 'gif'))) {
             $previewable = true;
             $info = aImageConverter::getInfo($source);
         }
         if ($previewable) {
             $iwidth = $info['width'];
             $iheight = $info['height'];
             // This is safe - based on sniffed file contents and not a user supplied extension
             $format = $info['format'];
             $dimensions = aDimensions::constrain($iwidth, $iheight, $format, $imagePreview);
             // A simple filename reveals less
             $imagename = "{$persistid}.{$format}";
             $url = "{$urlStem}/{$imagename}";
             $output = "{$dir}/{$imagename}";
             if (isset($info['newfile']) && $info['newfile'] || !file_exists($output)) {
                 if ($imagePreview['resizeType'] === 'c') {
                     $method = 'cropOriginal';
                 } else {
                     $method = 'scaleToFit';
                 }
                 sfContext::getInstance()->getLogger()->info("YY calling converter method {$method} width " . $dimensions['width'] . ' height ' . $dimensions['height']);
                 aImageConverter::$method($source, $output, $dimensions['width'], $dimensions['height']);
                 sfContext::getInstance()->getLogger()->info("YY after converter");
             }
         } else {
             // Don't try to provide an icon alternative to the preview here,
             // it's better to do that at the project and/or apostrophePlugin level
             // where we can style it better... the less we fake templating inside
             // a widget the better. See getFormat
             $url = false;
         }
         return $url;
     }
     return false;
 }
Esempio n. 17
0
 public function executeZipDemo(sfWebRequest $request)
 {
     if (!$this->get('zip_demo', false)) {
         throw new sfException('Zip demo feature is not enabled in properties.ini');
     }
     $uploads = aFiles::getUploadFolder();
     $uploadsDemo = "{$uploads}/apostrophedemo-uploads.zip";
     file_put_contents("{$uploads}/readme.txt", "This is the Symfony uploads folder. This file is here so that zipping this folder does not\nresult in an error when it happens to be empty. Move along, nothing to see here.");
     $this->zip($uploadsDemo, $uploads);
     // Has to be in the writable folder or we won't be able to write to it in many cases
     $data = aFiles::getWritableDataFolder();
     $dump = "{$data}/ademocontent.sql";
     $params = sfSyncContentTools::shellDatabaseParams(sfSyncContentTools::getDatabaseParams(sfContext::getInstance()->getConfiguration(), 'doctrine'));
     // Yes, you need to have mysql and mysqldump to use this feature.
     // However you can set app_syncContent_mysqldump to
     // the path of your mysqldump utility if it is called something
     // else or not in the PATH
     $mysql = sfConfig::get('app_syncContent_mysql', 'mysql');
     $mysqldump = sfConfig::get('app_syncContent_mysqldump', 'mysqldump');
     $cmd = escapeshellarg($mysqldump) . " --skip-opt --add-drop-table --create-options " . "--disable-keys --extended-insert --set-charset {$params} > " . escapeshellarg($dump);
     system($cmd, $result);
     if ($result != 0) {
         throw new sfException("mysqldump failed");
     }
     // You can explicitly set demo_password to an empty string to keep
     // the passwords in your demo unchanged
     $demoPassword = $this->get('demo_password', 'demo');
     if (!preg_match('/^\\w+$/', $demoPassword)) {
         throw new sfException("demo_password must contain only alphanumeric characters and underscores");
     }
     if ($demoPassword) {
         // New set of parameters for a temporary database in which we'll fix the passwords so that
         // the demo doesn't allow dictionary attacks on your real passwords
         $params = array();
         $params['dbname'] = $this->get('demo_tempdb');
         $params['username'] = $this->get('demo_tempuser');
         $params['password'] = $this->get('demo_temppassword');
         $params['host'] = $this->get('demo_temphost');
         $params = sfSyncContentTools::shellDatabaseParams($params);
         $cmd = escapeshellarg($mysql) . ' ' . $params . ' < ' . escapeshellarg($dump);
         system($cmd, $result);
         if ($result != 0) {
             throw new sfException("Unable to load sql into tempdb for password alteration. Did you configure tempdb, tempuser, temppassword and temphost in properties.ini?");
         }
         // I really ought to PDO this
         $cmd = escapeshellarg($mysql) . ' ' . $params;
         $out = popen($cmd, "w");
         // If we set the salt here, everyone who starts from the demo has the same salt.
         // If they change their passwords to real passwords, they are still vulnerable to
         // dictionary attack if their databases are compromised.
         // That's no good, so we'll fix the passwords with a clever trick in the demo fixtures
         // task that imports all this. We stash the demo password (not a secret) in the salt field
         // as cleartext for now, and the demo fixtures task grabs that, clears the salt field and
         // calls setPassword, resulting in a new, robustly unique salt on the new site.
         fwrite($out, "UPDATE sf_guard_user SET salt = '{$demoPassword}';\n");
         fwrite($out, "UPDATE sf_guard_user SET password = '';\n");
         $result = pclose($out);
         $cmd = escapeshellarg($mysqldump) . " --skip-opt --add-drop-table --create-options " . "--disable-keys --extended-insert --set-charset {$params} > " . escapeshellarg($dump);
         system($cmd, $result);
         if ($result != 0) {
             throw new sfException('Second mysqldump failed after password adjustment');
         }
     }
     $dataDemo = "{$uploads}/apostrophedemo-awritable.zip";
     $this->zip($dataDemo, $data);
     unlink($dump);
 }
 protected function lockTree()
 {
     $dir = aFiles::getWritableDataFolder(array('a', 'locks'));
     $file = "{$dir}/tree.lck";
     while (true) {
         $this->lockfp = fopen($file, 'a');
         if (!$this->lockfp) {
             sleep(1);
         } else {
             break;
         }
     }
     flock($this->lockfp, LOCK_EX);
 }
Esempio n. 19
0
 /**
  * DOCUMENT ME
  * @return mixed
  */
 public static function getDirectory()
 {
     return aFiles::getUploadFolder('media_items');
 }
 /**
  * DOCUMENT ME
  * @return mixed
  */
 protected static function getPersistentDir()
 {
     return aFiles::getWritableDataFolder(array("persistent_uploads"));
 }
Esempio n. 21
0
 /**
  * DOCUMENT ME
  * @return mixed
  */
 private function getCache()
 {
     if ($this->cache) {
         return $this->cache;
     }
     $cacheClass = sfConfig::get('app_a_embed_cache_class', 'sfFileCache');
     $this->cache = new $cacheClass(sfConfig::get('app_a_embed_cache_options', array('cache_dir' => aFiles::getWritableDataFolder(array('a_embed_cache')))));
     return $this->cache;
 }
 public static function loadData($test = null, $configuration = null)
 {
     self::$test = $test;
     self::$configuration = $configuration;
     // Load ALL the fixtures, including plugin fixtures, not just the app level fixtures!
     // ALSO: we only load the fixtures on the first functional test in a set. The rest of the time we
     // cheat and use a mysqldump file. There are various reasons why we cannot assume it is safe to
     // do this in the general case, including: modified fixtures, modified schemas, modified behaviors,
     // and modified Doctrine. But for consecutive runs in the same PHP invocation, we definitely
     // don't need to start from scratch!
     $root = sfConfig::get('sf_root_dir');
     $writable = aFiles::getWritableDataFolder();
     $cache = "{$writable}/test-fixtures-cache.sql";
     $reload = false;
     // TODO: I should check to see if a PID still exists somewhere to figure out if this is stale
     if (file_exists("{$writable}/test_set_pid")) {
         $processes = self::getProcesses();
         $pid = trim(file_get_contents("{$writable}/test_set_pid"));
         if (!isset($processes[$pid])) {
             // Stale
             unlink("{$writable}/test_set_pid");
             if (file_exists("{$writable}/test_set_first")) {
                 unlink("{$writable}/test_set_first");
             }
             self::info("{$writable}/test_set_pid is stale, reloading fixtures");
             $reload = true;
         } else {
             if (file_exists("{$writable}/test_set_first")) {
                 $reload = true;
                 self::info("first test in set, reloading fixtures");
                 unlink("{$writable}/test_set_first");
             } else {
                 self::info("later test in set, will not reload fixtures");
             }
         }
     } else {
         self::info("Not part of a test set, will reload fixtures");
         $reload = true;
     }
     if (!$reload) {
         $reload = !file_exists($cache) || filesize($cache) == 0;
     }
     $params = self::getDatabaseParams();
     // Attempt at autodetect that a reload is needed. This doesn't work well enough
     // because of modified schemas, modified behaviors, and modified Doctrine
     // if (!$reload)
     // {
     //   $fixtures = glob("$root/data/fixtures/*.yml");
     //   $plugins = sfContext::getInstance()->getConfiguration()->getPlugins();
     //   foreach ($plugins as $plugin)
     //   {
     //     $pluginFixtures = glob("$root/plugins/$plugin/data/fixtures/*.yml");
     //     $fixtures = array_merge($fixtures, $pluginFixtures);
     //   }
     //   foreach ($fixtures as $fixture)
     //   {
     //     if (filemtime($cache) < filemtime($fixture))
     //     {
     //       $reload = true;
     //       break;
     //     }
     //   }
     // }
     if ($reload) {
         self::info("Reloading fixtures and rebuilding model, filters and forms");
         self::info("(We would rather just reload fixtures but data-load does not clean up tables if there are are no entries for those tables in the fixtures, and that leaves traces of things created in those tables by previous tests. A doctrine:data-reload task is needed.)");
         system(escapeshellarg(sfConfig::get('sf_root_dir') . '/symfony') . ' doctrine:build --all --db --and-load --env=test --no-confirmation', $result);
         self::info("Reloaded fixtures");
         if ($result !== 0) {
             throw new sfException("Error loading data");
         }
         // Cache for next time
         $sh = 'mysqldump ' . self::shellDBParams($params) . ' > ' . escapeshellarg($cache);
         system($sh, $result);
         self::info("Cached fixtures with {$sh}");
         if ($result != 0) {
             throw new sfException("Error dumping fixtures to cache");
         }
     } else {
         self::info("Reloading fixtures data from {$cache}");
         system('mysql ' . self::shellDBParams($params) . ' < ' . escapeshellarg($cache), $result);
         if ($result != 0) {
             throw new sfException("Error reloading fixtures from cache");
         }
     }
     return;
 }
Esempio n. 23
0
 public static function clearAssetCache(sfFilesystem $fileSystem)
 {
     $assetDir = aFiles::getUploadFolder(array('asset-cache'));
     $fileSystem->remove(sfFinder::type('file')->in($assetDir));
     $cache = aAssets::getCache();
     $cache->clean();
 }