private function loadLinks()
 {
     if ($this->linksLoaded) {
         return;
     }
     // TODO: in new Bolt version use getContenttypeTablename instead of getTablename.
     $tableStructures = $this->app['storage']->getTablename('structures');
     $structures = $this->app['db']->fetchAll("SELECT id FROM {$tableStructures} WHERE status = 'published'");
     $availableStructures = util::array_pluck($structures, 'id');
     $contenttypes = $this->app['config']->get('contenttypes');
     foreach ($contenttypes as $contenttype) {
         if (isset($contenttype['fields']['structure_parent'])) {
             $contenttypeslug = $contenttype['slug'];
             $tablename = $this->app['storage']->getTablename($contenttypeslug);
             $stmt = $this->app['db']->prepare("SELECT id, structure_parent FROM {$tablename}");
             $res = $stmt->execute();
             while ($row = $stmt->fetch()) {
                 $id = intval($row['id']);
                 $parent = intval($row['structure_parent']);
                 // The $parent is only relevant if it exists and is published.
                 if (in_array($parent, $availableStructures)) {
                     $this->treeParents[$contenttypeslug][$id] = $parent;
                     $this->treeChildren[$parent][] = "{$contenttypeslug}/{$id}";
                 }
             }
         }
     }
     $this->linksLoaded = true;
 }
Exemple #2
0
 /**
  * Get the relations for one or more units of content, return the array with the taxonomy attached.
  *
  * @param array $content
  *
  * @return array $content
  */
 protected function getRelation($content)
 {
     $tablename = $this->getTablename("relations");
     $ids = util::array_pluck($content, 'id');
     if (empty($ids)) {
         return;
     }
     // Get the contenttype from first $content
     $contenttype = $content[util::array_first_key($content)]->contenttype['slug'];
     $query = sprintf("SELECT * FROM %s WHERE from_contenttype=? AND from_id IN (?) ORDER BY id", $tablename);
     $params = array($contenttype, $ids);
     $paramTypes = array(\PDO::PARAM_STR, DoctrineConn::PARAM_INT_ARRAY);
     $rows = $this->app['db']->executeQuery($query, $params, $paramTypes)->fetchAll();
     foreach ($rows as $row) {
         $content[$row['from_id']]->setRelation($row['to_contenttype'], $row['to_id']);
     }
     // switch it, flip it and reverse it. wop wop wop.
     $query = sprintf("SELECT * FROM %s WHERE to_contenttype=? AND to_id IN (?) ORDER BY id", $tablename);
     $params = array($contenttype, $ids);
     $paramTypes = array(\PDO::PARAM_STR, DoctrineConn::PARAM_INT_ARRAY);
     $rows = $this->app['db']->executeQuery($query, $params, $paramTypes)->fetchAll();
     foreach ($rows as $row) {
         $content[$row['to_id']]->setRelation($row['from_contenttype'], $row['from_id']);
     }
 }
Exemple #3
0
 public function getRepeaters($content)
 {
     $ids = util::array_pluck($content, 'id');
     if (empty($ids)) {
         return;
     }
     // Get the contenttype from first $content
     $contenttypeslug = $content[util::array_first_key($content)]->contenttype['slug'];
     $contenttype = $this->getContentType($contenttypeslug);
     $repo = $this->app['storage']->getRepository('Bolt\\Storage\\Entity\\FieldValue');
     foreach ($ids as $id) {
         foreach ($contenttype['fields'] as $fieldkey => $field) {
             if ($field['type'] == 'repeater') {
                 $collection = new RepeatingFieldCollection($this->app['storage'], $field);
                 $existingFields = $repo->getExistingFields($id, $contenttypeslug, $fieldkey) ?: [];
                 foreach ($existingFields as $group => $ids) {
                     $collection->addFromReferences($ids, $group);
                 }
                 $content[$id]->setValue($fieldkey, $collection);
             }
         }
     }
 }
 /**
  * Search through a single contenttype.
  *
  * Search, weigh and return the results.
  *
  * @param       $query
  * @param       $contenttype
  * @param       $fields
  * @param array $filter
  *
  * @return \Bolt\Legacy\Content
  */
 private function searchSingleContentType($query, $contenttype, $fields, array $filter = null)
 {
     // This could be even more configurable
     // (see also Content->getFieldWeights)
     $searchableTypes = ['text', 'textarea', 'html', 'markdown'];
     $table = $this->getContentTypeCollection($contenttype);
     // Build fields 'WHERE'
     $fieldsWhere = [];
     foreach ($fields as $field => $fieldconfig) {
         if (in_array($fieldconfig['type'], $searchableTypes)) {
             foreach ($query['words'] as $word) {
                 $fieldsWhere[] = sprintf('%s.%s LIKE %s', $table, $field, $this->app['db']->quote('%' . $word . '%'));
             }
         }
     }
     // make taxonomies work
     $taxonomytable = $this->getTablename('taxonomy');
     $taxonomies = $this->getContentTypeTaxonomy($contenttype);
     $tagsWhere = [];
     $tagsQuery = '';
     foreach ($taxonomies as $taxonomy) {
         if ($taxonomy['behaves_like'] == 'tags') {
             foreach ($query['words'] as $word) {
                 $tagsWhere[] = sprintf('%s.slug LIKE %s', $taxonomytable, $this->app['db']->quote('%' . $word . '%'));
             }
         }
     }
     // only add taxonomies if they exist
     if (!empty($taxonomies) && !empty($tagsWhere)) {
         $tagsQueryA = sprintf("%s.contenttype = '%s'", $taxonomytable, $contenttype);
         $tagsQueryB = implode(' OR ', $tagsWhere);
         $tagsQuery = sprintf(' OR (%s AND (%s))', $tagsQueryA, $tagsQueryB);
     }
     // Build filter 'WHERE"
     // @todo make relations work as well
     $filterWhere = [];
     if (!is_null($filter)) {
         foreach ($fields as $field => $fieldconfig) {
             if (isset($filter[$field])) {
                 $this->parseWhereParameter($table . '.' . $field, $filter[$field], $filterWhere);
             }
         }
     }
     // Build actual where
     $where = [];
     $where[] = sprintf("%s.status = 'published'", $table);
     $where[] = '(( ' . implode(' OR ', $fieldsWhere) . ' ) ' . $tagsQuery . ' )';
     $where = array_merge($where, $filterWhere);
     // Build SQL query
     $select = sprintf('SELECT %s.id FROM %s LEFT JOIN %s ON %s.id = %s.content_id WHERE %s GROUP BY %s.id', $table, $table, $taxonomytable, $table, $taxonomytable, implode(' AND ', $where), $table);
     // Run Query
     $results = $this->app['db']->fetchAll($select);
     if (!empty($results)) {
         $ids = implode(' || ', util::array_pluck($results, 'id'));
         $results = $this->getContent($contenttype, ['id' => $ids, 'returnsingle' => false]);
         // Convert and weight
         foreach ($results as $result) {
             $result->weighSearchResult($query);
         }
     }
     return $results;
 }
 /**
  * @author Xiao-Hu Tai
  * @param \Bolt\Content $record   The record to search similar content for.
  * @param array         $options  Options for custom queries.
  *
  * @return array Returns an array with the elements sorted by similarity.
  */
 function relatedContentByTags($record, $options = array())
 {
     $app = $this->app;
     $limit = isset($options['limit']) ? $options['limit'] : $this->config['limit'];
     $tablePrefix = $app['config']->get('general/database/prefix', 'bolt_');
     $taxonomyTable = sprintf('%staxonomy', $tablePrefix);
     $contenttypes = $app['config']->get('contenttypes');
     $filter = isset($options['contenttypes']) ? $options['contenttypes'] : false;
     // if set, filter contenttypes
     if ($filter) {
         $filterContenttypes = array();
         foreach ($filter as $contenttypeName) {
             if (isset($contenttypes[$contenttypeName])) {
                 $filterContenttypes[$contenttypeName] = $contenttypes[$contenttypeName];
             }
         }
         if ($filterContenttypes) {
             $contenttypes = $filterContenttypes;
         }
     }
     // Get all taxonomies that behave like tags and their values from $record.
     $tagsValues = array();
     $tagsTaxonomies = array();
     // If no taxonomies exist, then no matching items exist
     if (!isset($record->contenttype['taxonomy'])) {
         return array();
     }
     foreach ($record->contenttype['taxonomy'] as $key) {
         if ($app['config']->get('taxonomy/' . $key . '/behaves_like') == 'tags') {
             // only useful if values exist, otherwise just skip this taxonomy
             if ($record->taxonomy[$key]) {
                 $tagsValues[$key] = array_values($record->taxonomy[$key]);
                 $tagsTaxonomies[] = $key;
             }
         }
     }
     // Make the basic WHERE query for all behaves-like-tags values in $record.
     $queryWhere = array();
     foreach ($tagsValues as $tagName => $values) {
         $subqueryWhere = array();
         foreach ($values as $word) {
             $subqueryWhere[] = sprintf('%s.slug = "%s"', $taxonomyTable, $word);
         }
         $temp = sprintf('%s.taxonomytype = "%s"', $taxonomyTable, $tagName);
         $temp .= sprintf(' AND (%s)', implode(' OR ', $subqueryWhere));
         $queryWhere[] = $temp;
     }
     $queryWhere = implode(' OR ', $queryWhere);
     // Get all contenttypes (database tables) that have a similar behaves-like-tags taxonomies like $record
     $tables = array();
     foreach ($contenttypes as $key => $contenttype) {
         foreach ($contenttype['taxonomy'] as $taxonomyKey) {
             if (in_array($taxonomyKey, $tagsTaxonomies)) {
                 $tables[] = $contenttype['slug'];
                 break;
             }
         }
     }
     // Fetch results for every proper contenttype
     $results = array();
     foreach ($tables as $name) {
         $table = sprintf('%s%s', $tablePrefix, $name);
         $querySelect = '';
         $querySelect .= sprintf('SELECT %s.id FROM %s', $table, $table);
         $querySelect .= sprintf(' LEFT JOIN %s', $taxonomyTable);
         $querySelect .= sprintf(' ON %s.id = %s.content_id', $table, $taxonomyTable);
         $querySelect .= sprintf(' WHERE %s.status = "published"', $table);
         if ($name == $record->contenttype['slug']) {
             $querySelect .= sprintf('AND %s.id != ' . $record->id, $table);
         }
         $querySelect .= sprintf(' AND %s.contenttype = "%s"', $taxonomyTable, $name);
         $querySelect .= sprintf(' AND (%s)', $queryWhere);
         $queryResults = $app['db']->fetchAll($querySelect);
         if (!empty($queryResults)) {
             $ids = implode(' || ', \utilphp\util::array_pluck($queryResults, 'id'));
             $contents = $app['storage']->getContent($name, array('id' => $ids, 'returnsingle' => false));
             $results = array_merge($results, $contents);
         }
     }
     // Add similarities by tags and difference in publication dates.
     foreach ($results as $result) {
         $similarity = $this->calculateTaxonomySimilarity($record, $result, $tagsTaxonomies, $tagsValues, $options);
         $diff = $this->calculatePublicationDiff($record, $result);
         $result->similarity = $similarity;
         $result->diff = $diff;
     }
     // Sort results
     usort($results, array($this, 'compareSimilarity'));
     // Limit results
     $results = array_slice($results, 0, $limit);
     return $results;
 }
Exemple #6
0
 public function test_array_pluck()
 {
     $array = array(array('name' => 'Bob', 'age' => 37), array('name' => 'Fred', 'age' => 37), array('name' => 'Jane', 'age' => 29), array('name' => 'Brandon', 'age' => 20), array('age' => 41));
     $obj_array = array('bob' => (object) array('name' => 'Bob', 'age' => 37), 'fred' => (object) array('name' => 'Fred', 'age' => 37), 'jane' => (object) array('name' => 'Jane', 'age' => 29), 'brandon' => (object) array('name' => 'Brandon', 'age' => 20), 'invalid' => (object) array('age' => 41));
     $obj_array_expect = array('bob' => 'Bob', 'fred' => 'Fred', 'jane' => 'Jane', 'brandon' => 'Brandon');
     $this->assertEquals(array('Bob', 'Fred', 'Jane', 'Brandon'), util::array_pluck($array, 'name'));
     $this->assertEquals(array('Bob', 'Fred', 'Jane', 'Brandon', array('age' => 41)), util::array_pluck($array, 'name', TRUE, FALSE));
     $this->assertEquals($obj_array_expect, util::array_pluck($obj_array, 'name'));
     $this->assertEquals(array('Bob', 'Fred', 'Jane', 'Brandon'), util::array_pluck($obj_array, 'name', FALSE));
     $expected = array('Bob', 'Fred', 'Jane', 'Brandon', 'invalid' => (object) array('age' => 41));
     $this->assertEquals($expected, util::array_pluck($obj_array, 'name', FALSE, FALSE));
     $expected = array('Bob', 'Fred', 'Jane', 'Brandon', array('age' => 41));
     $this->assertEquals($expected, util::array_pluck($array, 'name', false, false));
 }