/**
  * DOCUMENT ME
  * @param mixed $arguments
  * @param mixed $options
  */
 protected function execute($arguments = array(), $options = array())
 {
     // initialize the database connection
     $databaseManager = new sfDatabaseManager($this->configuration);
     $connection = $databaseManager->getDatabase($options['connection'] ? $options['connection'] : null)->getConnection();
     $sql = new aMysql();
     $sql->query('UPDATE a_page SET published_at = NOW() where (archived IS FALSE OR archived IS NULL) AND substr(slug, 1, 1) = "/"');
     echo "published_at has been updated.\n";
 }
예제 #2
0
 public function getQuery()
 {
     // Explicit select() mandatory with orderByList
     $q = Doctrine::getTable($this->modelClass)->createQuery()->leftJoin($this->modelClass . '.Author a')->leftJoin($this->modelClass . '.Categories c')->select($this->modelClass . '.*, a.*, c.*');
     Doctrine::getTable($this->modelClass)->addPublished($q);
     if (isset($this->values['title_or_tag']) && $this->values['title_or_tag'] === 'title') {
         $this->handSelected = true;
         if (isset($this->values['blog_posts']) && count($this->values['blog_posts'])) {
             $q->andWhereIn('id', $this->values['blog_posts']);
             $q = aDoctrine::orderByList($q, $this->values['blog_posts']);
         } else {
             $q->andWhere('0 <> 0');
         }
         // Works way better when you actually return it!
         return $q;
     } else {
         if (isset($this->values['categories_list']) && count($this->values['categories_list']) > 0) {
             // This doesn't cut it because we wind up not knowing about the
             // other categories of each post, which breaks our "link to best page
             // for this post" algorithm
             // $q->andWhereIn('c.id', $this->values['categories_list']);
             // This would be nice but Doctrine croaks parsing it
             // $q->andWhere($this->modelClass . '.id IN (SELECT iblog.id FROM ' . $this->modelClass . ' iblog INNER JOIN iblog.Categories ic WITH ic.id IN ?)', array($this->values['categories_list']));
             // Let's cheat and use aMysql to pull the blog item IDs that have the relevant categories in a lightweight way,
             // then do a whereIn clause. It's not ideal, but it works well in practice
             $sql = new aMysql();
             $blogItemsForCategories = $sql->queryScalar('SELECT i.id FROM a_blog_item i INNER JOIN a_blog_item_to_category ic ON i.id = ic.blog_item_id AND ic.category_id IN :category_ids', array('category_ids' => $this->values['categories_list']));
             // So we use this after all, but we'll fetch all the categories for the posts in a second pass, sigh
             $q->andWhereIn($this->modelClass . '.id', $blogItemsForCategories);
         }
         if (isset($this->values['tags_list']) && strlen($this->values['tags_list']) > 0) {
             PluginTagTable::getObjectTaggedWithQuery($q->getRootAlias(), $this->values['tags_list'], $q, array('nb_common_tags' => 1));
         }
         if (!isset($this->values['count'])) {
             $this->values['count'] = 3;
         }
         $q->limit($this->values['count']);
         $q->orderBy('published_at desc');
         return $q;
     }
 }
 public static function filterForEngine($options)
 {
     // This method filters the virtual pages, tags and categories associated with a particular engine based on
     // specified criteria such as tag, category, publication date, etc.
     // Strategy: do Lucene queries and direct SQL queries that will get us all the info about relevant categories,
     // tags and virtual pages. Then turn that into a select distinct query for each of those things. The resulting
     // information is sufficient to populate the filters sidebar with options that are still relevant given the
     // other criteria in effect, and also to fetch the result pages (you'll want to do that with a LIMIT and an IN
     // query looking at the first n IDs returned by this method).
     // The options array looks like this. Note that all of these are optional and if each is unspecified or empty
     // no restriction is made on that particular basis. 'categoryIds' is used to limit to the categories associated
     // with the engine page, while 'categorySlug' is used to limit to a category specified by the user as a
     // filter. The 'q' option is Lucene search.
     // array(
     //   'q' => 'gromit',
     //   'categoryIds' => array(1, 3, 5),
     //   'categorySlug' => 'cheese',
     //   'tag' => 'wensleydale',
     //   'slugStem' => '@a_event_search_redirect',
     //   'year' => 2010, # Optional, if present only 2010 is shown
     //   'month' => 12, # Optional, if present only Dec. 2010 is shown
     //   'day' => 15, # Optional, if present only Dec. 15th 2010 is shown
     //   'byEventDateRange' => true, # For events only, joins with a_blog_item to get the range
     //   'byPublishedAt' => true, # For blog posts or pages
     // The returned value looks like this:
     // array(
     //   'categoriesInfo' => array('slug' => 'cheese', 'name' => 'Cheese'),
     //   'tagNames' => array('wensleydale'),
     //   'pageIds' => array(10, 15, 20, 25)
     $alphaSort = isset($options['alphaSort']) && $options['alphaSort'];
     if (isset($options['q']) && strlen($options['q'])) {
         $q = $options['q'];
         $key = strtolower(trim($q));
         $key = preg_replace('/\\s+/', ' ', $key);
         $replacements = sfConfig::get('app_a_search_refinements', array());
         if (isset($replacements[$key])) {
             $q = $replacements[$key];
         }
         if (isset($options['slugStem'])) {
             $q = "({$q}) AND slug:" . $options['slugStem'];
         }
         try {
             $values = aZendSearch::searchLuceneWithValues(Doctrine::getTable('aPage'), $q, aTools::getUserCulture());
         } catch (Exception $e) {
             // Lucene search error. TODO: display it nicely if they are always safe things to display. For now: just don't crash
             $values = array();
         }
         $now = date('YmdHis');
         $pageIds = array();
         foreach ($values as $value) {
             // Regardless of the above if it ain't published yet we can't see it.
             // We filter on that in the Doctrine query too but take advantage of
             // this chance to preempt a little work
             if ($value->published_at > $now) {
                 continue;
             }
             // 1.5: the names under which we store columns in Zend Lucene have changed to
             // avoid conflict with also indexing them
             $info = unserialize($value->info_stored);
             if (!aPageTable::checkPrivilege('view', $info)) {
                 continue;
             }
             $pageIds[] = $info['id'];
         }
     }
     $mysql = new aMysql();
     if (isset($options['slugStem'])) {
         $params['slug_pattern'] = $options['slugStem'] . '%';
     }
     // Select the relevant virtual pages for this engine
     $q = 'from a_page p ';
     // If alpha sort is present we need title slots
     if ($alphaSort) {
         if (!isset($options['culture'])) {
             $options['culture'] = aTools::getUserCulture();
         }
         $culture = $options['culture'];
         $q .= "\n        LEFT JOIN a_area a ON a.page_id = p.id AND a.name = 'title' AND a.culture = :culture\n        LEFT JOIN a_area_version v ON v.area_id = a.id AND a.latest_version = v.version \n        LEFT JOIN a_area_version_slot avs ON avs.area_version_id = v.id\n        LEFT JOIN a_slot s ON s.id = avs.slot_id ";
         $params['culture'] = $culture;
     }
     // Merge in categories. A left join unless we are restricted to certain categories
     $hasCategoryIds = isset($options['categoryIds']) && count($options['categoryIds']);
     $hasCategorySlug = isset($options['categorySlug']) && strlen($options['categorySlug']);
     $restrictedByCategory = $hasCategoryIds || $hasCategorySlug;
     if ($restrictedByCategory) {
         $cjoin = 'inner join';
     } else {
         $cjoin = 'left join';
     }
     $q .= $cjoin . ' a_page_to_category ptc on ptc.page_id = p.id ' . $cjoin . ' a_category c on ptc.category_id = c.id ';
     // The engine page is locked down to these categories. If none are specified it is not
     // locked down by category
     if ($hasCategoryIds) {
         $q .= "and c.id in :category_ids ";
         $params['category_ids'] = $options['categoryIds'];
     }
     // Bring in tags...
     $hasTag = isset($options['tag']) && strlen($options['tag']);
     if ($hasTag) {
         $q .= 'inner join ';
     } else {
         $q .= 'left join ';
     }
     $q .= 'tagging ti on ti.taggable_id = p.id and ti.taggable_model = "aPage" left join tag t on ti.tag_id = t.id ';
     // Get ready to filter posts or events chronologically
     $year = sprintf("%04d", isset($options['year']) ? $options['year'] : 0);
     $month = sprintf("%02d", isset($options['month']) ? $options['month'] : 0);
     $day = sprintf("%02d", isset($options['day']) ? $options['day'] : 0);
     $startYear = $year;
     $endYear = $year;
     if ($year > 0) {
         if ($month == 0) {
             // Do not mess up the two digit strings please
             $startMonth = '01';
             $startDay = '01';
             $endMonth = '12';
             $endDay = '31';
         } else {
             $startMonth = $month;
             $endMonth = $month;
             if ($day == 0) {
                 // Do not mess up the two digit strings please
                 $startDay = '01';
                 $endDay = '31';
             } else {
                 $startDay = $day;
                 $endDay = $day;
             }
         }
     } else {
         // For posts "today and forward" is not a relevant concept (and a separate clause
         // already makes sure we don't see unpublished stuff). For events we'll override
         // the start date below
         $startYear = '0000';
         $startMonth = '01';
         $startDay = '01';
         $endYear = '9999';
         $endMonth = '12';
         $endDay = '31';
     }
     $events = isset($options['byEventDateRange']) && $options['byEventDateRange'];
     if ($events && $startYear === '0000') {
         list($startYear, $startMonth, $startDay) = preg_split('/-/', date('Y-m-d'));
     }
     if ($events) {
         // The event's start and end dates are part of the blog item table
         $q .= ' inner join a_blog_item bi on bi.page_id = p.id ';
         $q .= "and bi.start_date <= :end_date ";
         $params['end_date'] = "{$endYear}-{$endMonth}-{$endDay}";
         $q .= "and bi.end_date >= :start_date ";
         $params['start_date'] = "{$startYear}-{$startMonth}-{$startDay}";
     }
     // Criteria for the pages themselves
     $q .= 'where p.slug like :slug_pattern ';
     // We often filter posts (not events) by a range of publication dates
     if (isset($options['byPublishedAt']) && $options['byPublishedAt']) {
         $q .= "and p.published_at <= :p_end_date ";
         $params['p_end_date'] = "{$endYear}-{$endMonth}-{$endDay}";
         $q .= "and p.published_at >= :p_start_date ";
         $params['p_start_date'] = "{$startYear}-{$startMonth}-{$startDay}";
     }
     // In no case do we show unpublished material
     $q .= 'and p.published_at <= NOW() and (p.archived IS NULL or p.archived IS FALSE) ';
     // ... But only those matching the Lucene search that already gave us specific IDs.
     // NOTE: if pageIds is not null and is empty, NOTHING should be returned
     // (someone searched for something that doesn't appear in the system)
     if (isset($pageIds)) {
         if (count($pageIds)) {
             $q .= 'and p.id in :pageIds ';
             $params['pageIds'] = $pageIds;
         } else {
             $q .= 'and 0 <> 0 ';
         }
     }
     if ($alphaSort) {
         $pagesOrderBy = 's.value asc';
     } elseif ($events) {
         $pagesOrderBy = 'bi.start_date asc, bi.start_time asc';
     } else {
         // Oops: blog presentation is typically descending, not ascending
         $pagesOrderBy = 'p.published_at desc';
     }
     // Separate queries, but quite fast because we're not bogged down in Doctrineland
     $c_q = $q;
     $t_q = $q;
     $p_q = $q;
     // We are filtering by this specific category
     if ($hasCategorySlug) {
         // Limit tags and pages by this specific category, but don't limit
         // categories by it, otherwise we can't present a choice of categories
         // meeting the other criteria
         $t_q .= "and c.slug = :category_slug ";
         $p_q .= "and c.slug = :category_slug ";
         $params['category_slug'] = $options['categorySlug'];
     }
     if ($hasTag) {
         // Limit pages and categories by this specific tag, but don't limit
         // tags by it, otherwise we can't present a choice of tags
         // meeting the other criteria
         $p_q .= 'and t.name = :tag_name ';
         $c_q .= 'and t.name = :tag_name ';
         $params['tag_name'] = $options['tag'];
     }
     // In the cases where we are looking for categories or tags, be sure to
     // discard the null rows from the LEFT JOINs. This is simpler than
     // determining when to switch them to INNER JOINs
     $result = array('categoriesInfo' => $mysql->query('select distinct c.slug, c.name ' . $c_q . 'and c.slug is not null order by c.name', $params), 'tagsByName' => $mysql->query('select t.name, count(distinct p.id) as t_count ' . $t_q . 'and t.name is not null group by t.name order by t.name', $params), 'tagsByPopularity' => $mysql->query('select t.name, count(distinct p.id) as t_count ' . $t_q . 'and t.name is not null group by t.name order by t_count desc limit 10', $params), 'pageIds' => $mysql->queryScalar('select distinct p.id ' . $p_q . ' order by ' . $pagesOrderBy, $params));
     return $result;
 }