/**
  * Set defaults
  *
  * @param  Vocabulary $vocabulary
  */
 public function setDefaults($vocabulary)
 {
     $vocabulary->setBaseDomain($this->getRequest()->getUriPrefix() . '/uri/');
     $vocabulary->setLanguage(sfConfig::get('app_default_language'));
     $vocabulary->setProfileId(sfConfig::get('app_vocabulary_profile_id'));
     parent::setDefaults($vocabulary);
 }
Exemple #2
0
 /**
  * Generates and makes a query into a external vocabulary for an exact
  * match for a particular concept.
  * @param Vocabulary $exvoc external vocabulary to query
  * @param string $exuri resource URI
  * @param string $lang language of label to query for
  * @return string label, or null if not found in vocabulary
  */
 protected function getExternalLabel($exvoc, $exuri, $lang)
 {
     if ($exvoc) {
         $exsparql = $exvoc->getSparql();
         $results = $exsparql->queryLabel($exuri, $lang);
         return isset($results[$lang]) ? $results[$lang] : null;
     } else {
         return null;
     }
 }
Exemple #3
0
 public function run()
 {
     $module = $this->controller->get('m', $this->controller->taxModule);
     if ($module == '') {
         $module = $this->controller->taxModule;
     }
     $voc = $this->controller->getVocabulary();
     if (is_object($voc)) {
         $v = $voc->id;
         $vob = $voc;
     } else {
         $v = $this->controller->get('v', 0);
         $vob = Vocabulary::model()->findByPk($v);
         if (!is_object($vob)) {
             throw new CHttpException(400, Yii::t('Xpress', 'Invalid Type ID.'));
         }
     }
     $this->controller->voc = $v;
     $propertyClassName = $vob->propertyClassName;
     $propertyModule = $vob->propertyModule;
     $property = '';
     if (Yii::app()->request->IsPostRequest) {
         // save posted data
         $model = $this->saveData($module, $v, $propertyModule, $propertyClassName);
     } else {
         // show edit form
         $id = $this->controller->get('id', 0);
         $model = $this->getTerm($id, $v);
         $property = $this->getProperty($id, $propertyClassName);
     }
     $this->controller->render('update', array('model' => $model, 'v' => $v, 'module' => $module, 'property' => $property, 'propertyModule' => $propertyModule, 'propertyClassName' => $propertyClassName));
 }
 /**
  * {@inheritdoc}
  */
 public function query()
 {
     $query = parent::query();
     $query->join('vocabulary_node_types', 'nt', 'v.vid = nt.vid');
     $query->fields('nt', array('type'));
     return $query;
 }
Exemple #5
0
    public function test_term_tree()
    {
        // create a vocabulary.
        if (Vocabulary::get('format_test')) {
            Vocabulary::get('format_test')->delete();
        }
        $v = Vocabulary::create(array('name' => 'format_test', 'description' => "Vocabulary used for testing Format::term_tree()", 'features' => array('hierarchical')));
        // nest some terms.
        /**
         * A
         * | \
         * B  C
         * |  | \
         * D  E  F 		// E has no descendants!
         * | \   | \
         * G  H  I  J	// G has no descendants!
         *   / \  \   \
         *  K   L  M   N
         **/
        $a = $v->add_term("A");
        $b = $v->add_term("B", $v->get_term($a->id));
        $c = $v->add_term("C", $v->get_term($a->id));
        $d = $v->add_term("D", $v->get_term($b->id));
        $e = $v->add_term("E", $v->get_term($c->id));
        $f = $v->add_term("F", $v->get_term($c->id));
        $g = $v->add_term("G", $v->get_term($d->id));
        $h = $v->add_term("H", $v->get_term($d->id));
        $i = $v->add_term("I", $v->get_term($f->id));
        $j = $v->add_term("J", $v->get_term($f->id));
        $k = $v->add_term("K", $v->get_term($h->id));
        $l = $v->add_term("L", $v->get_term($h->id));
        $m = $v->add_term("M", $v->get_term($i->id));
        $n = $v->add_term("N", $v->get_term($j->id));
        $tree_output = Format::term_tree($v->get_tree(), 'test', array('itemstart' => '<li>', 'itemattr' => '', 'liststart' => '<ol>', 'wrapper' => '%s'));
        $expected_output = <<<END
<ol class="tree" id="tree_test"><li>A<ol><li>B<ol><li>D<ol><li>G</li>
<li>H<ol><li>K</li>
<li>L</li>
</ol></li>
</ol></li>
</ol></li>
<li>C<ol><li>E</li>
<li>F<ol><li>I<ol><li>M</li>
</ol></li>
<li>J<ol><li>N</li>
</ol></li>
</ol></li>
</ol></li>
</ol></li>
</ol>
END;
        $result = $tree_output === $expected_output;
        if (!$result) {
            $this->output(sprintf('<strong>Expected:</strong><br><textarea rows="16">%s</textarea><br><strong>Got:</strong><br><textarea rows="16">%s</textarea>', $expected_output, $tree_output));
        }
        $this->assert_true($result, "Output does not match desired HTML");
        // clean up
        $v->delete();
    }
 /**
  * Find a model by its primary key.
  *
  * @param  mixed  $id
  * @param  array  $columns
  * @return \Illuminate\Support\Collection|static
  */
 public function find($id)
 {
     $model = Vocabulary::find($id);
     if ($model) {
         return $model;
     }
     throw new ResourceNotFoundException('Vocabulary was not found.');
 }
Exemple #7
0
 /**
  * find all vocavularies of current object
  * 
  * @param int $state vocabulary state
  * @return array Vocabulary
  */
 public function getVocabularies($state = Vocabulary::STATE_ACTIVE)
 {
     $criteria = new CDbCriteria();
     $criteria->join = "INNER JOIN " . SITE_ID . '_' . "taxonomy_term tt ON tt.v_id = t.id" . "\n INNER JOIN " . SITE_ID . '_' . "taxonomy_index ti ON ti.term_id = tt.id";
     if (is_numeric($this->taxonomy)) {
         $criteria->compare('t.id', $this->taxonomy);
     } else {
         $criteria->compare('t.alias', $this->taxonomy);
     }
     $criteria->compare('t.module', $this->module);
     $criteria->compare('t.state', $state);
     $objectId = (int) $this->getOwner()->{$this->objectAttribute};
     $criteria->compare('ti.object_id', $objectId);
     return Vocabulary::model()->findAll($criteria);
 }
Exemple #8
0
 /**
  * get all vocabularies by module
  * valid current vocabulary
  * 
  * @param int $type vocabulary
  * @param string $module module ID
  * 
  * @return array
  */
 protected function getVocabularies($type, $module)
 {
     $criteria = new CDbCriteria();
     $criteria->compare('module', $module);
     $criteria->order = 'name';
     $types = Vocabulary::model()->findAll($criteria);
     if (count($types)) {
         $types = CHtml::listData($types, 'id', 'name');
     }
     if ($type && !array_key_exists($type, $types)) {
         $types = array();
         //throw new CHttpException(500, 'Invalid Type');
     }
     return $types;
 }
 /**
  * Hydrates a vocabulary object with the data
  *
  * @param array $data
  * @param Vocabulary $object
  *
  * @return Vocabulary
  */
 public function hydrate(array $data, Vocabulary $object)
 {
     $object->setName($data['name']);
     $object->setIsEnabled($data['enabled']);
     $object->setDescription($data['description']);
     if (isset($data['id'])) {
         $object->setId($data['id']);
     }
     return $object;
 }
Exemple #10
0
 /**
  * Sets the Term objects associated to that type of object with that id in this vocabulary
  *
  * @param String the name of the object type
  * @param Integer The id of the object for which you want the terms
  * @param Array. The names of the terms to associate
  *
  * @return boolean. Whether the associations were successful or not
  **/
 public function set_object_terms($object_type, $id, $terms)
 {
     // no terms? then let's get out'a'here
     if (count($terms) == 0) {
         Plugins::act('term_detach_all_from_object_before', $this->id);
         $results = $this->get_object_terms($object_type, $id);
         foreach ($results as $term) {
             $term->dissociate($object_type, $id);
         }
         Plugins::act('term_detach_all_from_object_after', $this->id);
         return TRUE;
     }
     /*
      * First, let's clean the incoming tag text array, ensuring we have
      * a unique set of tag texts and slugs.
      */
     $term_ids_to_object = $clean_terms = array();
     foreach ((array) $terms as $term) {
         if (!in_array($term, array_keys($clean_terms))) {
             if (!in_array($slug = Utils::slugify($term), array_values($clean_terms))) {
                 $clean_terms[$term] = $slug;
             }
         }
     }
     /* Now, let's insert any *new* term display text or slugs into the terms table */
     $placeholders = Utils::placeholder_string(count($clean_terms));
     $sql_terms_exist = "SELECT id, term_display, term\n\t\t\tFROM {terms}\n\t\t\tWHERE term_display IN ({$placeholders})\n\t\t\tOR term IN ({$placeholders})\n\t\t\tAND vocabulary_id = ?";
     $params = array_merge(array_keys($clean_terms), array_values($clean_terms), (array) $this->id);
     $existing_terms = DB::get_results($sql_terms_exist, $params, 'Term');
     if (count($existing_terms) > 0) {
         /* Terms exist which match the term text or the term */
         foreach ($existing_terms as $existing_term) {
             /*
              * Term exists.
              * Attach object to term, then remove the term from creation list.
              */
             $existing_term->associate($object_type, $id);
             $term_ids_to_object[] = $existing_term->id;
             /*
              * We remove it from the clean_terms collection as we only
              * want to add to the terms table those terms which don't already exist
              */
             if (in_array($existing_term->term_display, array_keys($clean_terms))) {
                 unset($clean_terms[$existing_term->term_display]);
             }
             if (in_array($existing_term->term, array_values($clean_terms))) {
                 foreach ($clean_terms as $text => $slug) {
                     if ($slug == $existing_term->term) {
                         unset($clean_terms[$text]);
                         break;
                     }
                 }
             }
         }
     }
     /*
      * $clean_terms now contains an associative array of terms
      * we need to add to the main terms table, so add them
      *
      */
     foreach ($clean_terms as $new_term_text => $new_term_slug) {
         $term = new Term(array('term_display' => $new_term_text, 'term' => $new_term_slug));
         $this->add_term($term);
         $term->associate($object_type, $id);
         $term_ids_to_object[] = $term->id;
     }
     /*
      * Finally, remove the terms which are no longer associated with the object.
      */
     $repeat_questions = Utils::placeholder_string(count($term_ids_to_object));
     $sql_delete = "SELECT term_id FROM {object_terms}\n\t\t\tJOIN {terms} ON term_id = {terms}.id\n\t\t\tWHERE object_id = ? AND term_id NOT IN ({$repeat_questions}) AND object_type_id = ?\n\t\t\tAND {terms}.vocabulary_id = ?";
     $params = array_merge((array) $id, array_values($term_ids_to_object), (array) Vocabulary::object_type_id($object_type), (array) $this->id);
     $result = DB::get_column($sql_delete, $params);
     foreach ($result as $t) {
         $term = $this->get_term($t);
         $term->dissociate($object_type, $id);
     }
     return TRUE;
 }
Exemple #11
0
	/**
	 * function __get
	 * Overrides QueryRecord __get to implement custom object properties
	 * @param $name string Name of property to return
	 * @return mixed The requested field value
	 */
	public function __get( $name )
	{
		switch ( $name ) {
			case 'vocabulary':
				$out = Vocabulary::get_by_id( $this->vocabulary_id );
				break;
			case 'tag_text_searchable':
				// if it's got spaces, then quote it.
				if ( strpos( $this->term_display, ' ' ) !== false ) {
					$out = '\'' . str_replace( "'", "\'", $this->term_display ) . '\'';
				}
				else {
					$out = $this->term_display;
				}
				break;
			case 'count':
				$out = (int)$this->count();
				break;
			case 'id':
				return (int)parent::__get( $name );
			case 'info':
				return $this->get_info();
			default:
				$out = parent::__get( $name );
				break;
		}
		return $out;
	}
 /**
  * Declares an association between this object and a Vocabulary object.
  *
  * @param      Vocabulary $v
  * @return     void
  * @throws     PropelException
  */
 public function setVocabulary($v)
 {
     if ($v === null) {
         $this->setSchemeId(NULL);
     } else {
         $this->setSchemeId($v->getId());
     }
     $this->aVocabulary = $v;
 }
 /**
  * Remove a version if it's owner or a privileged person requested to do so
  **/
 public function theme_route_remove_addon_version($theme, $params)
 {
     $theme->post = Post::get(array('content_type' => Post::type('addon'), 'slug' => $params['slug']));
     // Check if the current user has access to this addon.
     $theme->permitted_versions = $this->addon_permitted_versions($theme->post);
     $vocab = Vocabulary::get(self::CATALOG_VOCABULARY);
     $term = $vocab->get_term($params['version']);
     if ($term && in_array($term->term, $theme->permitted_versions)) {
         $term->delete();
     }
     $remaining = $vocab->get_object_terms('addon', $theme->post->id);
     if (count($remaining) == 0) {
         // No versions left on this addon, so remove it entirely
         $theme->post->delete();
         // We should propably redirect to the $type overview page instead
         Utils::redirect(Site::get_url('habari'));
     }
     // Redirect so the displayed page uses the updated version list
     Utils::redirect($theme->post->permalink);
 }
 /**
  * get the top concepts for a vocabulary
  *
  * @return void
  * @param  Vocabulary $vocabulary
  */
 function getTopConcepts($vocabulary, $ts = null)
 {
     //get top concepts for vocabulary
     $c = new Criteria();
     $c->add(ConceptPeer::IS_TOP_CONCEPT, 1);
     $this->topConcepts = $vocabulary->getConcepts($c);
     return;
 }
Exemple #15
0
/**
 * Prepares a message based on parameters;
 *
 * This hook is called from MailManagerInterface->mail(). Note that hook_mail(),
 * unlike hook_mail_alter(), is only called on the $module argument to
 * MailManagerInterface->mail(), not all modules.
 *
 * @param $key
 *   An identifier of the mail.
 * @param $message
 *   An array to be filled in. Elements in this array include:
 *   - id: An ID to identify the mail sent. Look at module source code or
 *     MailManagerInterface->mail() for possible id values.
 *   - to: The address or addresses the message will be sent to. The
 *     formatting of this string must comply with RFC 2822.
 *   - subject: Subject of the email to be sent. This must not contain any
 *     newline characters, or the mail may not be sent properly.
 *     MailManagerInterface->mail() sets this to an empty
 *     string when the hook is invoked.
 *   - body: An array of lines containing the message to be sent. Drupal will
 *     format the correct line endings for you. MailManagerInterface->mail()
 *     sets this to an empty array when the hook is invoked. The array may
 *     contain either strings or objects implementing
 *     \Drupal\Component\Render\MarkupInterface.
 *   - from: The address the message will be marked as being from, which is
 *     set by MailManagerInterface->mail() to either a custom address or the
 *     site-wide default email address when the hook is invoked.
 *   - headers: Associative array containing mail headers, such as From,
 *     Sender, MIME-Version, Content-Type, etc.
 *     MailManagerInterface->mail() pre-fills several headers in this array.
 * @param $params
 *   An array of parameters supplied by the caller of
 *   MailManagerInterface->mail().
 *
 * @see \Drupal\Core\Mail\MailManagerInterface::mail()
 */
function hook_mail($key, &$message, $params)
{
    $account = $params['account'];
    $context = $params['context'];
    $variables = array('%site_name' => \Drupal::config('system.site')->get('name'), '%username' => $account->getDisplayName());
    if ($context['hook'] == 'taxonomy') {
        $entity = $params['entity'];
        $vocabulary = Vocabulary::load($entity->id());
        $variables += array('%term_name' => $entity->name, '%term_description' => $entity->description, '%term_id' => $entity->id(), '%vocabulary_name' => $vocabulary->label(), '%vocabulary_description' => $vocabulary->getDescription(), '%vocabulary_id' => $vocabulary->id());
    }
    // Node-based variable translation is only available if we have a node.
    if (isset($params['node'])) {
        /** @var \Drupal\node\NodeInterface $node */
        $node = $params['node'];
        $variables += array('%uid' => $node->getOwnerId(), '%url' => $node->url('canonical', array('absolute' => TRUE)), '%node_type' => node_get_type_label($node), '%title' => $node->getTitle(), '%teaser' => $node->teaser, '%body' => $node->body);
    }
    $subject = strtr($context['subject'], $variables);
    $body = strtr($context['message'], $variables);
    $message['subject'] .= str_replace(array("\r", "\n"), '', $subject);
    $message['body'][] = MailFormatHelper::htmlToText($body);
}
Exemple #16
0
 /**
  * Get posts by vocabulary
  * - vocabulary => an array describing parameters related to vocabularies attached to posts. This can be one of two forms:
  *   - object-based, in which an array of Term objects are passed
  *     - any => posts associated with any of the terms are returned
  *     - all => posts associated with all of the terms are returned
  *     - not => posts associated with none of the terms are returned
  *   - property-based, in which an array of vocabulary names and associated fields are passed
  *     - vocabulary_name:term => a vocabulary name and term slug pair or array of vocabulary name and term slug pairs, any of which can be associated with the posts
  *     - vocabulary_name:term_display => a vocabulary name and term display pair or array of vocabulary name and term display pairs, any of which can be associated with the posts
  *     - vocabulary_name:not:term => a vocabulary name and term slug pair or array of vocabulary name and term slug pairs, none of which can be associated with the posts
  *     - vocabulary_name:not:term_display => a vocabulary name and term display pair or array of vocabulary name and term display pairs, none of which can be associated with the posts
  *     - vocabulary_name:all:term => a vocabulary name and term slug pair or array of vocabulary name and term slug pairs, all of which must be associated with the posts
  *     - vocabulary_name:all:term_display => a vocabulary name and term display pair or array of vocabulary name and term display pairs, all of which must be associated with the posts
  */
 public function test_get_posts_by_vocabulary()
 {
     // setup
     // create a couple Vocabularies and Terms
     if (Vocabulary::get("fizz")) {
         Vocabulary::get("fizz")->delete();
     }
     $fizz = Vocabulary::create(array('name' => 'fizz', 'description' => 'Vocabulary for Posts testing.', 'features' => array('free')));
     $fizz_term = new Term(array('term' => 'fizz', 'term_display' => 'Fizz'));
     $fizz->add_term($fizz_term);
     $extra_fizz_term = new Term(array('term' => 'extra fizzy', 'term_display' => 'Extra Fizzy'));
     $fizz->add_term($extra_fizz_term);
     if (Vocabulary::get("buzz")) {
         Vocabulary::get("buzz")->delete();
     }
     $buzz = Vocabulary::create(array('name' => 'buzz', 'description' => 'Another Vocabulary for Posts testing.', 'features' => array('free')));
     $buzz_term = new Term(array('term' => 'buzz', 'term_display' => 'Buzz'));
     $buzz->add_term($buzz_term);
     // create some Posts and associate them with the two Vocabularies
     for ($i = 1; $i <= 20; $i++) {
         $post = Post::create(array('title' => "Test Post {$i}", 'content' => 'If this were really a post...', 'user_id' => $this->user->id, 'status' => Post::status('published'), 'content_type' => Post::type('entry'), 'pubdate' => DateTime::date_create(time())));
         $post->info->testing_vocab = 1;
         $post->info->i = $i;
         $post->info->commit();
         if ($i % 3 === 0) {
             $fizz->set_object_terms('post', $post->id, array($fizz_term->term));
         }
         if ($i % 5 === 0) {
             $buzz->set_object_terms('post', $post->id, array($buzz_term->term));
         }
     }
     // Object-based syntax
     $total_posts = Posts::count_total();
     $any_vocab_posts = Posts::get(array('ignore_permissions' => true, 'vocabulary' => array("any" => array($fizz_term, $buzz_term)), 'nolimit' => 1, 'count' => 'DISTINCT {posts}.id'));
     $all_vocab_posts = Posts::get(array('ignore_permissions' => true, 'vocabulary' => array("all" => array($fizz_term, $buzz_term)), 'nolimit' => 1, 'count' => 'DISTINCT {posts}.id'));
     $not_vocab_posts = Posts::get(array('ignore_permissions' => true, 'vocabulary' => array("not" => array($fizz_term, $buzz_term)), 'nolimit' => 1, 'count' => 'DISTINCT {posts}.id'));
     $this->assert_true($any_vocab_posts > $all_vocab_posts, "Any: {$any_vocab_posts} should be greater than All: {$all_vocab_posts}");
     $this->assert_true($not_vocab_posts > $all_vocab_posts, "Not: {$not_vocab_posts} should be greater than All: {$all_vocab_posts}");
     $this->assert_true($not_vocab_posts < $total_posts, "Not: {$not_vocab_posts} should be less than Total: {$total_posts}");
     $this->assert_equal($any_vocab_posts + $not_vocab_posts, $total_posts, "Any: {$any_vocab_posts} plus Not: {$not_vocab_posts} should equal Total: {$total_posts}");
     // Property-based syntax
     $any_vocab_posts = Posts::get(array('ignore_permissions' => true, 'vocabulary' => array("fizz:term" => "fizz", "buzz:term" => "buzz"), 'nolimit' => 1, 'count' => 'DISTINCT {posts}.id'));
     $all_vocab_posts = Posts::get(array('ignore_permissions' => true, 'vocabulary' => array("fizz:all:term" => "fizz", "buzz:all:term" => "buzz"), 'nolimit' => 1, 'count' => 'DISTINCT {posts}.id'));
     $not_vocab_posts = Posts::get(array('ignore_permissions' => true, 'vocabulary' => array("fizz:not:term" => "fizz", "buzz:not:term" => "buzz"), 'nolimit' => 1, 'count' => 'DISTINCT {posts}.id'));
     $this->assert_true($any_vocab_posts > $all_vocab_posts, "Any: {$any_vocab_posts} should be greater than All: {$all_vocab_posts}");
     $this->assert_true($not_vocab_posts > $all_vocab_posts, "Not: {$not_vocab_posts} should be greater than All: {$all_vocab_posts}");
     $this->assert_true($not_vocab_posts < $total_posts, "Not: {$not_vocab_posts} should be less than Total: {$total_posts}");
     $this->assert_equal($any_vocab_posts + $not_vocab_posts, $total_posts, "Any: {$any_vocab_posts} plus Not: {$not_vocab_posts} should equal Total: {$total_posts}");
     // teardown
     Posts::get(array('ignore_permissions' => true, 'has:info' => 'testing_vocab', 'nolimit' => 1))->delete();
     $fizz->delete();
     $buzz->delete();
 }
Exemple #17
0
 /**
  * find terms recursive
  * 
  * @param Term $parent
  */
 protected function findTermsRecursive($parent, $level = 0, $path = '/', $state = Term::STATE_ACTIVE, $orderBy = 'ordering')
 {
     $data = $parent->attributes;
     $data['level'] = $level++;
     $vob = Vocabulary::model()->findByPk($parent->v_id);
     if (is_object($vob)) {
         $propertyClassName = $vob->propertyClassName;
         if (!empty($propertyClassName)) {
             $model = new $propertyClassName();
             $property = $model->findByAttributes(array('term_id' => $parent->id, 'status' => $state));
             if (is_object($property)) {
                 $properties = $property->attributes;
                 unset($properties['id'], $properties['status'], $properties['creation_datetime'], $properties['last_update'], $properties['created_by'], $properties['updated_by'], $properties['term_id']);
                 $data['properties'] = $properties;
             }
         }
     }
     $children = $parent->children(array('order' => $orderBy, 'condition' => 'children.state=:state', 'params' => array(':state' => $state)));
     if (is_array($children) && count($children)) {
         $data['children'] = array();
         foreach ($children as $term) {
             Yii::trace('findTermsRecursive in ' . $orderBy, 'system.db.abc');
             $data['children'][] = $this->findTermsRecursive($term, $level, '/', $state, $orderBy);
         }
     }
     return $data;
 }
 public function __construct(\Vocabulary $vocab)
 {
     $this->itemArray["@context"] = "http://rdaregistry.info/Contexts/concepts_langmap.jsonld";
     $this->vocab = $vocab;
     $this->setReleaseFromGithub();
     $this->vocabArray["@id"] = $vocab->getUri();
     $this->vocabArray["@type"] = "ConceptScheme";
     $this->vocabArray['title'] = [$vocab->getLanguage() => $vocab->getName()];
     $this->vocabArray['description'] = [$vocab->getLanguage() => $vocab->getNote()];
     $this->vocabArray["token"] = $vocab->getToken();
     $this->vocabArray["prefix"] = $vocab->getPrefix();
     $status = \ConceptPeer::getConceptByUri($vocab->getStatus()->getUri());
     $this->vocabArray['status'] = ["@id" => $status->getUri(), "label" => $status->getPrefLabel()];
     $this->vocabArray['omr_api'] = "http://api.metadataregistry.org/vocabularies/" . $vocab->getId();
     $this->vocabArray['omr_home'] = "http://metadataregistry.org/vocabulary/show/id/" . $vocab->getId() . ".html";
     $this->vocabArray['documentation'] = $vocab->getUrl();
     $this->vocabArray['tags'] = ["en" => $this->getTags($this->vocab->getCommunity())];
     $this->vocabArray["count"] = $vocab->countConcepts();
     $this->vocabArray["languages"] = $this->getLanguages($vocab->getLanguages());
     $this->vocabArray["dateOfPublication"] = $this->getDateOfPublication();
     $this->itemArray["@graph"][] = $this->vocabArray;
     $concepts = $this->getConcepts();
     if ($concepts) {
         foreach ($concepts as $concept) {
             $this->itemArray["@graph"][] = $this->getConceptPropertyArray($concept);
         }
     }
 }
Exemple #19
0
 /**
  * Renames terms.
  * If the master term exists, the terms will be merged with it.
  * If not, it will be created first.
  *
  * @param mixed $master The Term to which they should be renamed, or the slug, text or id of it
  * @param Array $tags The tag text, slugs or ids to be renamed
  **/
 public function merge($master, $tags, $object_type = 'post')
 {
     $type_id = Vocabulary::object_type_id($object_type);
     $post_ids = array();
     $tag_names = array();
     // get the master term
     $master_term = $this->get_term($master);
     if (!isset($master_term->term)) {
         // it didn't exist, so we assume it's tag text and create it
         $master_term = $this->add_term($master);
         if (!$master_term) {
             return;
         }
         $master_ids = array();
     } else {
         // get the posts the tag is already on so we don't duplicate them
         $master_ids = $master_term->objects($object_type);
     }
     // get array of existing tags first to make sure we don't conflict with a new master tag
     foreach ($tags as $tag) {
         // if this is the master tag, there's nothing to do
         if ($tag == $master) {
             continue;
         }
         $term = $this->get_term($tag);
         // get all the post ID's tagged with this tag
         $posts = $term->objects($object_type);
         $ok_to_delete = true;
         // if there actually are posts, let's link those up with the new tag now
         if (count($posts) > 0) {
             // only try and add the master tag to posts it's not already on
             $post_ids = array_diff($posts, $master_ids);
             foreach ($post_ids as $post_id) {
                 $r = $master_term->associate($object_type, $post_id);
                 // if we failed linking this post, we can keep trying others, but don't delete this tag when finished
                 if ($r == false) {
                     $ok_to_delete = false;
                 } else {
                     // otherwise, we did in fact merge a tag - make sure the tag is in the list of ones we merged
                     $tag_names[$tag] = $tag;
                     // and disassociate this post from the existing tag
                     $term->dissociate($object_type, $post_id);
                 }
             }
         }
         // if it's still ok to delete the tag entirely, do so
         if ($ok_to_delete) {
             $this->delete_term($term->id);
         } else {
             // otherwise, log a special message that we didn't delete it
             EventLog::log(_t('Not all posts tagged "%1$s" could be reassigned to "%2$s". They have been left alone.', array($tag, $master)), 'err', 'vocabulary', 'habari');
         }
     }
     EventLog::log(sprintf(_n('Term %1$s in the %2$s vocabulary has been renamed to %3$s.', 'Terms %1$s in the %2$s vocabulary have been renamed to %3$s.', count($tags)), implode(', ', $tag_names), $this->name, $master), 'info', 'vocabulary', 'habari');
 }
 public function get_menus($as_array = false)
 {
     $vocabularies = Vocabulary::get_all();
     $outarray = array();
     foreach ($vocabularies as $index => $menu) {
         if (!$menu->term_menu) {
             // check for the term_menu feature we added.
             unset($vocabularies[$index]);
         } else {
             if ($as_array) {
                 $outarray[$menu->id] = $menu->name;
             }
         }
     }
     if ($as_array) {
         return $outarray;
     } else {
         return $vocabularies;
     }
 }
Exemple #21
0
	/**
	 * Returns a post or posts based on supplied parameters.
	 * @todo <b>THIS CLASS SHOULD CACHE QUERY RESULTS!</b>
	 *
	 * @param array $paramarray An associative array of parameters, or a querystring.
	 * The following keys are supported:
	 * - id => a post id or array of post ids
	 * - not:id => a post id or array of post ids to exclude
	 * - slug => a post slug or array of post slugs
	 * - not:slug => a post slug or array of post slugs to exclude
	 * - user_id => an author id or array of author ids
	 * - content_type => a post content type or array post content types
	 * - not:content_type => a post content type or array post content types to exclude
	 * - status => a post status, an array of post statuses, or 'any' for all statuses
	 * - year => a year of post publication
	 * - month => a month of post publication, ignored if year is not specified
	 * - day => a day of post publication, ignored if month and year are not specified
	 * - before => a timestamp to compare post publication dates
	 * - after => a timestamp to compare post publication dates
	 * - month_cts => return the number of posts published in each month
	 * - criteria => a literal search string to match post content
	 * - title => an exact case-insensitive match to a post title
	 * - title_search => a search string that acts only on the post title
	 * - has:info => a post info key or array of post info keys, which should be present
	 * - all:info => a post info key and value pair or array of post info key and value pairs, which should all be present and match
	 * - not:all:info => a post info key and value pair or array of post info key and value pairs, to exclude if all are present and match
	 * - any:info => a post info key and value pair or array of post info key and value pairs, any of which can match
	 * - not:any:info => a post info key and value pair or array of post info key and value pairs, to exclude if any are present and match
	 * - vocabulary => an array describing parameters related to vocabularies attached to posts. This can be one of two forms:
	 *   - object-based, in which an array of Term objects are passed
	 *     - any => posts associated with any of the terms are returned
	 *     - all => posts associated with all of the terms are returned
	 *     - not => posts associated with none of the terms are returned
	 *   - property-based, in which an array of vocabulary names and associated fields are passed
	 *     - vocabulary_name:term => a vocabulary name and term slug pair or array of vocabulary name and term slug pairs, any of which can be associated with the posts
	 *     - vocabulary_name:term_display => a vocabulary name and term display pair or array of vocabulary name and term display pairs, any of which can be associated with the posts
	 *     - vocabulary_name:not:term => a vocabulary name and term slug pair or array of vocabulary name and term slug pairs, none of which can be associated with the posts
	 *     - vocabulary_name:not:term_display => a vocabulary name and term display pair or array of vocabulary name and term display pairs, none of which can be associated with the posts
	 *     - vocabulary_name:all:term => a vocabulary name and term slug pair or array of vocabulary name and term slug pairs, all of which must be associated with the posts
	 *     - vocabulary_name:all:term_display => a vocabulary name and term display pair or array of vocabulary name and term display pairs, all of which must be associated with the posts
	 * - limit => the maximum number of posts to return, implicitly set for many queries
	 * - nolimit => do not implicitly set limit
	 * - offset => amount by which to offset returned posts, used in conjunction with limit
	 * - page => the 'page' of posts to return when paging, sets the appropriate offset
	 * - count => return the number of posts that would be returned by this request
	 * - orderby => how to order the returned posts
	 * - groupby => columns by which to group the returned posts, for aggregate functions
	 * - having => for selecting posts based on an aggregate function
	 * - where => manipulate the generated WHERE clause. Currently broken, see https://trac.habariproject.org/habari/ticket/1383
	 * - add_select => an array of clauses to be added to the generated SELECT clause.
	 * - fetch_fn => the function used to fetch data, one of 'get_results', 'get_row', 'get_value', 'get_query'
	 *
	 * Further description of parameters, including usage examples, can be found at
	 * http://wiki.habariproject.org/en/Dev:Retrieving_Posts
	 *
	 * @return array An array of Post objects, or a single post object, depending on request
	 */
	public static function get( $paramarray = array() )
	{
		static $presets;

		// If $paramarray is a string, use it as a Preset
		if(is_string($paramarray)) {
			$paramarray = array('preset' => $paramarray);
		}

		// If $paramarray is a querystring, convert it to an array
		$paramarray = Utils::get_params( $paramarray );

		// If a preset is defined, get the named array and merge it with the provided parameters,
		// allowing the additional $paramarray settings to override the preset
		if(isset($paramarray['preset'])) {
			if(!isset($presets)) {
				$presets = Plugins::filter('posts_get_all_presets', $presets, $paramarray['preset']);
			}
			if(isset($presets[$paramarray['preset']])) {
				$preset = Plugins::filter('posts_get_update_preset', $presets[$paramarray['preset']], $paramarray['preset'], $paramarray);
				$paramarray = array_merge($paramarray, $preset);
			}
		}

		// let plugins alter the param array before we use it. could be useful for modifying search results, etc.
		$paramarray = Plugins::filter( 'posts_get_paramarray', $paramarray );

		$join_params = array();
		$params = array();
		$fns = array( 'get_results', 'get_row', 'get_value', 'get_query' );
		$select_ary = array();

		// Default fields to select, everything by default
		foreach ( Post::default_fields() as $field => $value ) {
			$select_ary[$field] = "{posts}.$field AS $field";
			$select_distinct[$field] = "{posts}.$field";
		}

		// Default parameters
		$orderby = 'pubdate DESC';

		// Define the WHERE sets to process and OR in the final SQL statement
		if ( isset( $paramarray['where'] ) && is_array( $paramarray['where'] ) ) {
			$wheresets = $paramarray['where'];
		}
		else {
			$wheresets = array( array() );
		}

		/* Start building the WHERE clauses */

		$wheres = array();
		$joins = array();

		// If the request as a textual WHERE clause, skip the processing of the $wheresets since it's empty
		if ( isset( $paramarray['where'] ) && is_string( $paramarray['where'] ) ) {
			$wheres[] = $paramarray['where'];
		}
		else {
			foreach ( $wheresets as $paramset ) {
				// Safety mechanism to prevent empty queries
				$where = array();
				$paramset = array_merge( (array) $paramarray, (array) $paramset );
				// $nots= preg_grep( '%^not:(\w+)$%iu', (array) $paramset );

				if ( isset( $paramset['id'] ) ) {
					if ( is_array( $paramset['id'] ) ) {
						array_walk( $paramset['id'], create_function( '&$a,$b', '$a = intval( $a );' ) );
						$where[] = "{posts}.id IN (" . implode( ',', array_fill( 0, count( $paramset['id'] ), '?' ) ) . ")";
						$params = array_merge( $params, $paramset['id'] );
					}
					else {
						$where[] = "{posts}.id = ?";
						$params[] = (int) $paramset['id'];
					}
				}
				if ( isset( $paramset['not:id'] ) ) {
					if ( is_array( $paramset['not:id'] ) ) {
						array_walk( $paramset['not:id'], create_function( '&$a,$b', '$a = intval( $a );' ) );
						$where[] = "{posts}.id NOT IN (" . implode( ',', array_fill( 0, count( $paramset['not:id'] ), '?' ) ) . ")";
						$params = array_merge( $params, $paramset['not:id'] );
					}
					else {
						$where[] = "{posts}.id != ?";
						$params[] = (int) $paramset['not:id'];
					}
				}
				if ( isset( $paramset['status'] ) && ( $paramset['status'] != 'any' ) && ( 0 !== $paramset['status'] ) ) {
					if ( is_array( $paramset['status'] ) ) {
						// remove 'any' from the list if we have an array
						$paramset['status'] = array_diff( $paramset['status'], array( 'any' ) );
						array_walk( $paramset['status'], create_function( '&$a,$b', '$a = Post::status( $a );' ) );
						$where[] = "{posts}.status IN (" . implode( ',', array_fill( 0, count( $paramset['status'] ), '?' ) ) . ")";
						$params = array_merge( $params, $paramset['status'] );
					}
					else {
						$where[] = "{posts}.status = ?";
						$params[] = (int) Post::status( $paramset['status'] );
					}
				}
				if ( isset( $paramset['content_type'] ) && ( $paramset['content_type'] != 'any' ) && ( 0 !== $paramset['content_type'] ) ) {
					if ( is_array( $paramset['content_type'] ) ) {
						// remove 'any' from the list if we have an array
						$paramset['content_type'] = array_diff( $paramset['content_type'], array( 'any' ) );
						array_walk( $paramset['content_type'], create_function( '&$a,$b', '$a = Post::type( $a );' ) );
						$where[] = "{posts}.content_type IN (" . implode( ',', array_fill( 0, count( $paramset['content_type'] ), '?' ) ) . ")";
						$params = array_merge( $params, $paramset['content_type'] );
					}
					else {
						$where[] = "{posts}.content_type = ?";
						$params[] = (int) Post::type( $paramset['content_type'] );
					}
				}
				if ( isset( $paramset['not:content_type'] ) ) {
					if ( is_array( $paramset['not:content_type'] ) ) {
						array_walk( $paramset['not:content_type'], create_function( '&$a,$b', '$a = Post::type( $a );' ) );
						$where[] = "{posts}.content_type NOT IN (" . implode( ',', array_fill( 0, count( $paramset['not:content_type'] ), '?' ) ) . ")";
						$params = array_merge( $params, $paramset['not:content_type'] );
					}
					else {
						$where[] = "{posts}.content_type != ?";
						$params[] = (int) Post::type( $paramset['not:content_type'] );
					}
				}
				if ( isset( $paramset['slug'] ) ) {
					if ( is_array( $paramset['slug'] ) ) {
						$where[] = "{posts}.slug IN (" . implode( ',', array_fill( 0, count( $paramset['slug'] ), '?' ) ) . ")";
						$params = array_merge( $params, $paramset['slug'] );
					}
					else {
						$where[] = "{posts}.slug = ?";
						$params[] = (string) $paramset['slug'];
					}
				}
				
				if ( isset( $paramset['not:slug'] ) ) {
					if ( is_array( $paramset['not:slug'] ) ) {
						$where[] = "{posts}.slug NOT IN (" . implode( ',', array_fill( 0, count( $paramset['not:slug'] ), '?' ) ) . ")";
						$params = array_merge( $params, $paramset['not:slug'] );
					}
					else {
						$where[] = "{posts}.slug != ?";
						$params[] = (string) $paramset['not:slug'];
					}
				}
				
				if ( isset( $paramset['user_id'] ) && 0 !== $paramset['user_id'] ) {
					if ( is_array( $paramset['user_id'] ) ) {
						array_walk( $paramset['user_id'], create_function( '&$a,$b', '$a = intval( $a );' ) );
						$where[] = "{posts}.user_id IN (" . implode( ',', array_fill( 0, count( $paramset['user_id'] ), '?' ) ) . ")";
						$params = array_merge( $params, $paramset['user_id'] );
					}
					else {
						$where[] = "{posts}.user_id = ?";
						$params[] = (int) $paramset['user_id'];
					}

				}

				if ( isset( $paramset['vocabulary'] ) ) {
					
					if ( is_string( $paramset['vocabulary'] ) ) {
						$paramset['vocabulary'] = Utils::get_params( $paramset['vocabulary'] );
					}
					
					// parse out the different formats we accept arguments in into a single mutli-dimensional array of goodness
					$paramset['vocabulary'] = self::vocabulary_params( $paramset['vocabulary'] );
					$object_id = Vocabulary::object_type_id( 'post' );
					
					$all = array();
					$any = array();
					$not = array();
					
					if ( isset( $paramset['vocabulary']['all'] ) ) {
						$all = $paramset['vocabulary']['all'];
					}
					
					if ( isset( $paramset['vocabulary']['any'] ) ) {
						$any = $paramset['vocabulary']['any'];
					}
					
					if ( isset( $paramset['vocabulary']['not'] ) ) {
						$not = $paramset['vocabulary']['not'];
					}
					
					foreach ( $all as $vocab => $value ) {
						
						foreach ( $value as $field => $terms ) {
							
							// we only support these fields to search by
							if ( !in_array( $field, array( 'id', 'term', 'term_display' ) ) ) {
								continue;
							}
							
							$joins['term2post_posts'] = ' JOIN {object_terms} ON {posts}.id = {object_terms}.object_id';
							$joins['terms_term2post'] = ' JOIN {terms} ON {object_terms}.term_id = {terms}.id';
							$joins['terms_vocabulary'] = ' JOIN {vocabularies} ON {terms}.vocabulary_id = {vocabularies}.id';
							
							$where[] = '{vocabularies}.name = ? AND {terms}.' . $field . ' IN ( ' . Utils::placeholder_string( $terms ) . ' ) AND {object_terms}.object_type_id = ?';
							$params[] = $vocab;
							$params = array_merge( $params, $terms );
							$params[] = $object_id;
							
						}
						
						// this causes no posts to match if combined with 'any' below and should be re-thought... somehow
						$groupby = implode( ',', $select_distinct );
						$having = 'count(*) = ' . count( $terms );
						
					}
					
					foreach ( $any as $vocab => $value ) {
						
						foreach ( $value as $field => $terms ) {
							
							// we only support these fields to search by
							if ( !in_array( $field, array( 'id', 'term', 'term_display' ) ) ) {
								continue;
							}
							
							$joins['term2post_posts'] = ' JOIN {object_terms} ON {posts}.id = {object_terms}.object_id';
							$joins['terms_term2post'] = ' JOIN {terms} ON {object_terms}.term_id = {terms}.id';
							$joins['terms_vocabulary'] = ' JOIN {vocabularies} ON {terms}.vocabulary_id = {vocabularies}.id';
							
							$where[] = '{vocabularies}.name = ? AND {terms}.' . $field . ' IN ( ' . Utils::placeholder_string( $terms ) . ' ) AND {object_terms}.object_type_id = ?';
							$params[] = $vocab;
							$params = array_merge( $params, $terms );
							$params[] = $object_id;
							
						}
						
					}
					
					foreach ( $not as $vocab => $value ) {
						
						foreach ( $value as $field => $terms ) {
							
							// we only support these fields to search by
							if ( !in_array( $field, array( 'id', 'term', 'term_display' ) ) ) {
								continue;
							}
							
							$where[] = 'NOT EXISTS ( SELECT 1
								FROM {object_terms} 
								JOIN {terms} ON {terms}.id = {object_terms}.term_id 
								JOIN {vocabularies} ON {terms}.vocabulary_id = {vocabularies}.id  
								WHERE {terms}.' . $field . ' IN (' . Utils::placeholder_string( $terms ) . ')
								AND {object_terms}.object_id = {posts}.id 
								AND {object_terms}.object_type_id = ? 
								AND {vocabularies}.name = ?
							)';
							$params = array_merge( $params, array_values( $terms ) );
							$params[] = $object_id;
							$params[] = $vocab;
							
						}
						
					}
					
				}

				if ( isset( $paramset['criteria'] ) ) {
					// this regex matches any unicode letters (\p{L}) or numbers (\p{N}) inside a set of quotes (but strips the quotes) OR not in a set of quotes
					preg_match_all( '/(?<=")([\p{L}\p{N}]+[^"]*)(?=")|([\p{L}\p{N}]+)/u', $paramset['criteria'], $matches );
					foreach ( $matches[0] as $word ) {
						$where[] .= "( LOWER( {posts}.title ) LIKE ? OR  LOWER( {posts}.content ) LIKE ?)";
						$params[] = '%' . MultiByte::strtolower( $word ) . '%';
						$params[] = '%' . MultiByte::strtolower( $word ) . '%';  // Not a typo (there are two ? in the above statement)
					}
				}

				if ( isset( $paramset['title'] ) ) {
					$where[] .= "LOWER( {posts}.title ) LIKE ?";
					$params[] = MultiByte::strtolower( $paramset['title'] );
				}

				if ( isset( $paramset['title_search'] ) ) {
					// this regex matches any unicode letters (\p{L}) or numbers (\p{N}) inside a set of quotes (but strips the quotes) OR not in a set of quotes
					preg_match_all( '/(?<=")([\p{L}\p{N}]+[^"]*)(?=")|([\p{L}\p{N}]+)/u', $paramset['title_search'], $matches );
					foreach ( $matches[0] as $word ) {
						$where[] .= " LOWER( {posts}.title ) LIKE ? ";
						$params[] = '%' . MultiByte::strtolower( $word ) . '%';
					}
				}

				if ( isset( $paramset['all:info'] ) || isset( $paramset['info'] ) ) {

					// merge the two possibile calls together
					$infos = array_merge( isset( $paramset['all:info'] ) ? $paramset['all:info'] : array(), isset( $paramset['info'] ) ? $paramset['info'] : array() );

					if ( Utils::is_traversable( $infos ) ) {
						$pi_count = 0;
						foreach ( $infos as $info_key => $info_value ) {
							$pi_count++;
							$joins['info_' . $info_key] = " LEFT JOIN {postinfo} ipi{$pi_count} ON {posts}.id = ipi{$pi_count}.post_id AND ipi{$pi_count}.name = ? AND ipi{$pi_count}.value = ?";
							$join_params[] = $info_key;
							$join_params[] = $info_value;
							$where[] = "ipi{$pi_count}.name <> ''";

							$select_ary["info_{$info_key}_value"] = "ipi{$pi_count}.value AS info_{$info_key}_value";
							$select_distinct["info_{$info_key}_value"] = "info_{$info_key}_value";
						}
					}

				}

				if ( isset( $paramset['any:info'] ) ) {
					if ( Utils::is_traversable( $paramset['any:info'] ) ) {
						$pi_count = 0;
						$pi_where = array();
						foreach ( $paramset['any:info'] as $info_key => $info_value ) {
							$pi_count++;

							$join_params[] = $info_key;
							if ( is_array( $info_value ) ) {
								$joins['any_info_' . $info_key] = " LEFT JOIN {postinfo} aipi{$pi_count} ON {posts}.id = aipi{$pi_count}.post_id AND aipi{$pi_count}.name = ? AND aipi{$pi_count}.value IN (" .Utils::placeholder_string( count( $info_value ) ).")";
								$join_params = array_merge( $join_params, $info_value );
							}
							else {
								$joins['any_info_' . $info_key] = " LEFT JOIN {postinfo} aipi{$pi_count} ON {posts}.id = aipi{$pi_count}.post_id AND aipi{$pi_count}.name = ? AND aipi{$pi_count}.value = ?";
								$join_params[] = $info_value;
							}

							$pi_where[] = "aipi{$pi_count}.name <> ''";

							$select_ary["info_{$info_key}_value"] = "aipi{$pi_count}.value AS info_{$info_key}_value";
							$select_distinct["info_{$info_key}_value"] = "info_{$info_key}_value";
						}
						$where[] = '(' . implode( ' OR ', $pi_where ) . ')';
					}
				}

				if ( isset( $paramset['has:info'] ) ) {
					$the_ins = array();
					$has_info = Utils::single_array( $paramset['has:info'] );
					$pi_count = 0;
					$pi_where = array();
					foreach ( $has_info as $info_name ) {
						$pi_count++;
						$joins['has_info_' . $info_name] = " LEFT JOIN {postinfo} hipi{$pi_count} ON {posts}.id = hipi{$pi_count}.post_id AND hipi{$pi_count}.name = ?";
						$join_params[] = $info_name;
						$pi_where[] = "hipi{$pi_count}.name <> ''";

						$select_ary["info_{$info_name}_value"] = "hipi{$pi_count}.value AS info_{$info_name}_value";
						$select_distinct["info_{$info_name}_value"] = "info_{$info_name}_value";
					}
					$where[] = '(' . implode( ' OR ', $pi_where ) . ')';
				}

				if ( isset( $paramset['not:all:info'] ) || isset( $paramset['not:info'] ) ) {

					// merge the two possible calls together
					$infos = array_merge( isset( $paramset['not:all:info'] ) ? $paramset['not:all:info'] : array(), isset( $paramset['not:info'] ) ? $paramset['not:info'] : array() );

					if ( Utils::is_traversable( $infos ) ) {
						$the_ins = array();

						foreach ( $infos as $info_key => $info_value ) {

							$the_ins[] = ' ({postinfo}.name = ? AND {postinfo}.value = ? ) ';
							$params[] = $info_key;
							$params[] = $info_value;

						}

						$where[] = '
							{posts}.id NOT IN (
							SELECT post_id FROM {postinfo}
							WHERE ( ' . implode( ' OR ', $the_ins ) . ' )
							GROUP BY post_id
							HAVING COUNT(*) = ' . count( $infos ) . ' )
						';
						// see that hard-coded number? sqlite wets itself if we use a bound parameter... don't change that

					}

				}

				if ( isset( $paramset['not:any:info'] ) ) {

					if ( Utils::is_traversable( $paramset['not:any:info'] ) ) {

						foreach ( $paramset['not:any:info'] as $info_key => $info_value ) {

							$the_ins[] = ' ({postinfo}.name = ? AND {postinfo}.value = ? ) ';
							$params[] = $info_key;
							$params[] = $info_value;

						}

						$where[] = '
							{posts}.id NOT IN (
								SELECT post_id FROM {postinfo}
								WHERE ( ' . implode( ' OR ', $the_ins ) . ' )
							)
						';

					}

				}

				/**
				 * Build the statement needed to filter by pubdate:
				 * If we've got the day, then get the date;
				 * If we've got the month, but no date, get the month;
				 * If we've only got the year, get the whole year.
				 */
				if ( isset( $paramset['day'] ) && isset( $paramset['month'] ) && isset( $paramset['year'] ) ) {
					$where[] = 'pubdate BETWEEN ? AND ?';
					$start_date = sprintf( '%d-%02d-%02d', $paramset['year'], $paramset['month'], $paramset['day'] );
					$start_date = HabariDateTime::date_create( $start_date );
					$params[] = $start_date->sql;
					$params[] = $start_date->modify( '+1 day -1 second' )->sql;
					//$params[] = date( 'Y-m-d H:i:s', mktime( 0, 0, 0, $paramset['month'], $paramset['day'], $paramset['year'] ) );
					//$params[] = date( 'Y-m-d H:i:s', mktime( 23, 59, 59, $paramset['month'], $paramset['day'], $paramset['year'] ) );
				}
				elseif ( isset( $paramset['month'] ) && isset( $paramset['year'] ) ) {
					$where[] = 'pubdate BETWEEN ? AND ?';
					$start_date = sprintf( '%d-%02d-%02d', $paramset['year'], $paramset['month'], 1 );
					$start_date = HabariDateTime::date_create( $start_date );
					$params[] = $start_date->sql;
					$params[] = $start_date->modify( '+1 month -1 second' )->sql;
					//$params[] = date( 'Y-m-d H:i:s', mktime( 0, 0, 0, $paramset['month'], 1, $paramset['year'] ) );
					//$params[] = date( 'Y-m-d H:i:s', mktime( 23, 59, 59, $paramset['month'] + 1, 0, $paramset['year'] ) );
				}
				elseif ( isset( $paramset['year'] ) ) {
					$where[] = 'pubdate BETWEEN ? AND ?';
					$start_date = sprintf( '%d-%02d-%02d', $paramset['year'], 1, 1 );
					$start_date = HabariDateTime::date_create( $start_date );
					$params[] = $start_date->sql;
					$params[] = $start_date->modify( '+1 year -1 second' )->sql;
					//$params[] = date( 'Y-m-d H:i:s', mktime( 0, 0, 0, 1, 1, $paramset['year'] ) );
					//$params[] = date( 'Y-m-d H:i:s', mktime( 0, 0, -1, 1, 1, $paramset['year'] + 1 ) );
				}

				if ( isset( $paramset['after'] ) ) {
					$where[] = 'pubdate > ?';
					$params[] = HabariDateTime::date_create( $paramset['after'] )->sql;
				}

				if ( isset( $paramset['before'] ) ) {
					$where[] = 'pubdate < ?';
					$params[] = HabariDateTime::date_create( $paramset['before'] )->sql;
				}

				// Concatenate the WHERE clauses
				if ( count( $where ) > 0 ) {
					$wheres[] = ' (' . implode( ' AND ', $where ) . ') ';
				}
			}
		}

		// Only show posts to which the current user has permission
		if ( isset( $paramset['ignore_permissions'] ) ) {
			$master_perm_where = '';
		}
		else {
			// This set of wheres will be used to generate a list of post_ids that this user can read
			$perm_where = array();
			$perm_where_denied = array();
			$params_where = array();
			$where = array();

			// Get the tokens that this user is granted or denied access to read
			$read_tokens = isset( $paramset['read_tokens'] ) ? $paramset['read_tokens'] : ACL::user_tokens( User::identify(), 'read', true );
			$deny_tokens = isset( $paramset['deny_tokens'] ) ? $paramset['deny_tokens'] : ACL::user_tokens( User::identify(), 'deny', true );

			// If a user can read any post type, let him
			if ( User::identify()->can( 'post_any', 'read' ) ) {
				$perm_where = array( 'post_any' => '(1=1)' );
			}
			else {
				// If a user can read his own posts, let him
				if ( User::identify()->can( 'own_posts', 'read' ) ) {
					$perm_where['own_posts_id'] = '{posts}.user_id = ?';
					$params_where[] = User::identify()->id;
				}

				// If a user can read specific post types, let him
				$permitted_post_types = array();
				foreach ( Post::list_active_post_types() as $name => $posttype ) {
					if ( User::identify()->can( 'post_' . Utils::slugify( $name ), 'read' ) ) {
						$permitted_post_types[] = $posttype;
					}
				}
				if ( count( $permitted_post_types ) > 0 ) {
					$perm_where[] = '{posts}.content_type IN (' . implode( ',', $permitted_post_types ) . ')';
				}

				// If a user can read posts with specific tokens, let him
				if ( count( $read_tokens ) > 0 ) {
					$joins['post_tokens__allowed'] = ' LEFT JOIN {post_tokens} pt_allowed ON {posts}.id= pt_allowed.post_id AND pt_allowed.token_id IN ('.implode( ',', $read_tokens ).')';
					$perm_where['perms_join_null'] = 'pt_allowed.post_id IS NOT NULL';
				}

				// If a user has access to read other users' unpublished posts, let him
				if ( User::identify()->can( 'post_unpublished', 'read' ) ) {
					$perm_where[] = '({posts}.status <> ? AND {posts}.user_id <> ?)';
					$params_where[] = Post::status( 'published' );
					$params_where[] = User::identify()->id;
				}

			}

			$params_where_denied = array();
			// If a user is denied access to all posts, do so
			if ( User::identify()->cannot( 'post_any' ) ) {
				$perm_where_denied = array( '(1=0)' );
			}
			else {
				// If a user is denied read access to specific post types, deny him
				$denied_post_types = array();
				foreach ( Post::list_active_post_types() as $name => $posttype ) {
					if ( User::identify()->cannot( 'post_' . Utils::slugify( $name ) ) ) {
						$denied_post_types[] = $posttype;
					}
				}
				if ( count( $denied_post_types ) > 0 ) {
					$perm_where_denied[] = '{posts}.content_type NOT IN (' . implode( ',', $denied_post_types ) . ')';
				}

				// If a user is denied access to read other users' unpublished posts, deny it
				if ( User::identify()->cannot( 'post_unpublished' ) ) {
					$perm_where_denied[] = '({posts}.status = ? OR {posts}.user_id = ?)';
					$params_where_denied[] = Post::status( 'published' );
					$params_where_denied[] = User::identify()->id;
				}

			}

			// This doesn't work yet because you can't pass these arrays by reference
			Plugins::act( 'post_get_perm_where', $perm_where, $params_where, $paramarray );
			Plugins::act( 'post_get_perm_where_denied', $perm_where_denied, $params_where_denied, $paramarray );
						
			// Set up the merge params
			$merge_params = array( $join_params, $params );
			
			// If there are granted permissions to check, add them to the where clause
			if ( count( $perm_where ) == 0 && !isset( $joins['post_tokens__allowed'] ) ) {
				// You have no grants.  You get no posts.
				$where['perms_granted'] = '(1=0)';
			}
			elseif ( count( $perm_where ) > 0 ) {
				$where['perms_granted'] = '
					(' . implode( ' OR ', $perm_where ) . ')
				';
				$merge_params[] = $params_where;
			}

			if ( count( $deny_tokens ) > 0 ) {
				$joins['post_tokens__denied'] = ' LEFT JOIN {post_tokens} pt_denied ON {posts}.id= pt_denied.post_id AND pt_denied.token_id IN ('.implode( ',', $deny_tokens ).')';
				$perm_where_denied['perms_join_null'] = 'pt_denied.post_id IS NULL';
			}

			// If there are denied permissions to check, add them to the where clause
			if ( count( $perm_where_denied ) > 0 ) {
				$where['perms_denied'] = '
					(' . implode( ' AND ', $perm_where_denied ) . ')
				';
				$merge_params[] = $params_where_denied;
			}
			
			// Merge the params
			$params = call_user_func_array( 'array_merge', $merge_params );

			// AND the separate permission-related WHERE clauses
			$master_perm_where = implode( ' AND ', $where );
		}

		// Extract the remaining parameters which will be used onwards
		// For example: page number, fetch function, limit
		$paramarray = new SuperGlobal( $paramarray );
		$extract = $paramarray->filter_keys( 'page', 'fetch_fn', 'count', 'orderby', 'groupby', 'limit', 'offset', 'nolimit', 'having', 'add_select' );
		foreach ( $extract as $key => $value ) {
			$$key = $value;
		}

		// Define the LIMIT if it does not exist, unless specific posts are requested or we're getting the monthly counts
		if ( !isset( $limit ) && !isset( $paramset['id'] ) && !isset( $paramset['slug'] ) && !isset( $paramset['month_cts'] ) ) {
			$limit = Options::get( 'pagination' ) ? (int) Options::get( 'pagination' ) : 5;
		}
		elseif ( !isset( $limit ) ) {
			$selected_posts = 0;
			if ( isset( $paramset['id'] ) ) {
				$selected_posts += count( Utils::single_array( $paramset['id'] ) );
			}
			if ( isset( $paramset['slug'] ) ) {
				$selected_posts += count( Utils::single_array( $paramset['slug'] ) );
			}
			$limit = $selected_posts > 0 ? $selected_posts : '';
		}

		// Calculate the OFFSET based on the page number
		if ( isset( $page ) && is_numeric( $page ) && !isset( $paramset['offset'] ) ) {
			$offset = ( intval( $page ) - 1 ) * intval( $limit );
		}

		/**
		 * Determine which fetch function to use:
		 * If it is specified, make sure it is valid (based on the $fns array defined at the beginning of this function);
		 * Else, use 'get_results' which will return a Posts array of Post objects.
		 */
		if ( isset( $fetch_fn ) ) {
			if ( ! in_array( $fetch_fn, $fns ) ) {
				$fetch_fn = $fns[0];
			}
		}
		else {
			$fetch_fn = $fns[0];
		}
		
		
		// If the orderby has a function in it, try to create a select field for it with an alias
		if ( strpos( $orderby, '(' ) !== false ) {
			$orders = explode( ',', $orderby );
			$ob_index = 0;
			foreach ( $orders as $key => $order ) {
				if ( !preg_match( '%(?P<field>.+)\s+(?P<direction>DESC|ASC)%i', $order, $order_matches ) ) {
					$order_matches = array(
						'field' => $order,
						'direction' => '',
					);
				}
				
				if ( strpos( $order_matches['field'], '(' ) !== false ) {
					$ob_index++;
					$field = 'orderby' . $ob_index;
					$select_ary[$field] = "{$order_matches['field']} AS $field";
					$select_distinct[$field] = "{$order_matches['field']} AS $field";
					$orders[$key] = $field . ' ' . $order_matches['direction'];
				}
			}
			$orderby = implode( ', ', $orders );
		}

		// Add arbitrary fields to the select clause for sorting and output
		if ( isset( $add_select ) ) {
			$select_ary = array_merge( $select_ary, $add_select );
		}
		

		/**
		 * Turn the requested fields into a comma-separated SELECT field clause
		 */
		$select = implode( ', ', $select_ary );

		/**
		 * If a count is requested:
		 * Replace the current fields to select with a COUNT();
		 * Change the fetch function to 'get_value';
		 * Remove the ORDER BY since it's useless.
		 * Remove the GROUP BY (tag search added it)
		 */
		if ( isset( $count ) ) {
			$select = "COUNT($count)";
			$fetch_fn = 'get_value';
			$orderby = '';
			$groupby = '';
			$having = '';
		}

		// If the month counts are requested, replaced the select clause
		if ( isset( $paramset['month_cts'] ) ) {
			if ( isset( $paramset['vocabulary'] ) ) {
				$select = 'MONTH(FROM_UNIXTIME(pubdate)) AS month, YEAR(FROM_UNIXTIME(pubdate)) AS year, COUNT(DISTINCT {posts}.id) AS ct';
			}
			else {
				$select = 'MONTH(FROM_UNIXTIME(pubdate)) AS month, YEAR(FROM_UNIXTIME(pubdate)) AS year, COUNT(*) AS ct';
			}
			$groupby = 'year, month';
			if ( !isset( $paramarray['orderby'] ) ) {
				$orderby = 'year, month';
			}
		}


		// Remove the LIMIT if 'nolimit'
		// Doing this first should allow OFFSET to work
		if ( isset( $nolimit ) ) {
			$limit = '';
		}

		// Define the LIMIT and add the OFFSET if it exists
		if ( !empty( $limit ) ) {
			$limit = " LIMIT $limit";
			if ( isset( $offset ) ) {
				$limit .= " OFFSET $offset";
			}
		}
		else {
			$limit = '';
		}

		/* All SQL parts are constructed, on to real business! */

		/**
		 * Build the final SQL statement
		 */
		$query = '
			SELECT DISTINCT ' . $select . '
			FROM {posts} ' . "\n " . implode( "\n ", $joins ) . "\n";

		if ( count( $wheres ) > 0 ) {
			$query .= ' WHERE (' . implode( " \nOR\n ", $wheres ) . ')';
			$query .= ( $master_perm_where == '' ) ? '' : ' AND (' . $master_perm_where . ')';
		}
		elseif ( $master_perm_where != '' ) {
			$query .= ' WHERE (' . $master_perm_where . ')';
		}
		$query .= ( ! isset( $groupby ) || $groupby == '' ) ? '' : ' GROUP BY ' . $groupby;
		$query .= ( ! isset( $having ) || $having == '' ) ? '' : ' HAVING ' . $having;
		$query .= ( ( $orderby == '' ) ? '' : ' ORDER BY ' . $orderby ) . $limit;

		/**
		 * DEBUG: Uncomment the following line to display everything that happens in this function
		 */
		//print_R('<pre>'.$query.'</pre>');
		//Utils::debug( $paramarray, $fetch_fn, $query, $params );
		//Session::notice($query);

		if ( 'get_query' == $fetch_fn ) {
			return array(
				$query,
				$params
			);
		}
		
		/**
		 * Execute the SQL statement using the PDO extension
		 */
		DB::set_fetch_mode( PDO::FETCH_CLASS );
		DB::set_fetch_class( 'Post' );
		$results = DB::$fetch_fn( $query, $params, 'Post' );

		//Utils::debug( $paramarray, $fetch_fn, $query, $params, $results );
		//var_dump( $query );

		/**
		 * Return the results
		 */
		if ( 'get_results' != $fetch_fn ) {
			// Since a single result was requested, return a single Post object.
			return $results;
		}
		elseif ( is_array( $results ) ) {
			// With multiple results, return a Posts array of Post objects.
			$c = __CLASS__;
			$return_value = new $c( $results );
			$return_value->get_param_cache = $paramarray;
			return $return_value;
		}
	}
Exemple #22
0
 /**
  * function __get
  * Overrides QueryRecord __get to implement custom object properties
  * @param $name string Name of property to return
  * @return mixed The requested field value
  **/
 public function __get($name)
 {
     switch ($name) {
         case 'vocabulary':
             return Vocabulary::get_by_id($this->vocabulary_id);
         default:
             return parent::__get($name);
     }
 }
Exemple #23
0
 /**
  * Returns an unordered list of all used Tags
  */
 public function theme_show_tags($theme)
 {
     $limit = Options::get(__CLASS__ . '__tags_count');
     $sql = "\n\t\t\tSELECT t.term AS slug, t.term_display AS text, count(tp.object_id) as ttl\n\t\t\tFROM {terms} t\n\t\t\tINNER JOIN {object_terms} tp\n\t\t\tON t.id=tp.term_id\n\t\t\tINNER JOIN {posts} p\n\t\t\tON p.id=tp.object_id AND p.status = ?\n\t\t\tWHERE t.vocabulary_id = ? AND tp.object_type_id = ?\n\t\t\tGROUP BY t.term, t.term_display\n\t\t\tORDER BY t.term_display\n\t\t\tLIMIT {$limit}\n\t\t";
     $tags = DB::get_results($sql, array(Post::status('published'), Tags::vocabulary()->id, Vocabulary::object_type_id('post')));
     foreach ($tags as $index => $tag) {
         $tags[$index]->url = URL::get('display_entries_by_tag', array('tag' => $tag->slug));
     }
     $theme->taglist = $tags;
     return $theme->fetch('taglist');
 }
Exemple #24
0
 /**
  * Returns a post or posts based on supplied parameters.
  * @todo <b>THIS CLASS SHOULD CACHE QUERY RESULTS!</b>
  *
  * @param array $paramarray An associative array of parameters, or a querystring.
  * The following keys are supported:
  * - id => a post id or array of post ids
  * - not:id => a post id or array of post ids to exclude
  * - slug => a post slug or array of post slugs
  * - not:slug => a post slug or array of post slugs to exclude
  * - user_id => an author id or array of author ids
  * - content_type => a post content type or array post content types
  * - not:content_type => a post content type or array post content types to exclude
  * - status => a post status, an array of post statuses, or 'any' for all statuses
  * - year => a year of post publication
  * - month => a month of post publication, ignored if year is not specified
  * - day => a day of post publication, ignored if month and year are not specified
  * - before => a timestamp to compare post publication dates
  * - after => a timestamp to compare post publication dates
  * - month_cts => return the number of posts published in each month
  * - criteria => a literal search string to match post content or title
  * - title => an exact case-insensitive match to a post title
  * - title_search => a search string that acts only on the post title
  * - has:info => a post info key or array of post info keys, which should be present
  * - all:info => a post info key and value pair or array of post info key and value pairs, which should all be present and match
  * - not:all:info => a post info key and value pair or array of post info key and value pairs, to exclude if all are present and match
  * - any:info => a post info key and value pair or array of post info key and value pairs, any of which can match
  * - not:any:info => a post info key and value pair or array of post info key and value pairs, to exclude if any are present and match
  * - vocabulary => an array describing parameters related to vocabularies attached to posts. This can be one of two forms:
  *   - object-based, in which an array of Term objects are passed
  *     - any => posts associated with any of the terms are returned
  *     - all => posts associated with all of the terms are returned
  *     - not => posts associated with none of the terms are returned
  *   - property-based, in which an array of vocabulary names and associated fields are passed
  *     - vocabulary_name:term => a vocabulary name and term slug pair or array of vocabulary name and term slug pairs, any of which can be associated with the posts
  *     - vocabulary_name:term_display => a vocabulary name and term display pair or array of vocabulary name and term display pairs, any of which can be associated with the posts
  *     - vocabulary_name:not:term => a vocabulary name and term slug pair or array of vocabulary name and term slug pairs, none of which can be associated with the posts
  *     - vocabulary_name:not:term_display => a vocabulary name and term display pair or array of vocabulary name and term display pairs, none of which can be associated with the posts
  *     - vocabulary_name:all:term => a vocabulary name and term slug pair or array of vocabulary name and term slug pairs, all of which must be associated with the posts
  *     - vocabulary_name:all:term_display => a vocabulary name and term display pair or array of vocabulary name and term display pairs, all of which must be associated with the posts
  * - on_query_built => a closure that accepts a Query as a parameter, allowing a plugin to alter the Query for this request directly
  * - limit => the maximum number of posts to return, implicitly set for many queries
  * - nolimit => do not implicitly set limit
  * - offset => amount by which to offset returned posts, used in conjunction with limit
  * - page => the 'page' of posts to return when paging, sets the appropriate offset
  * - count => return the number of posts that would be returned by this request
  * - orderby => how to order the returned posts
  * - groupby => columns by which to group the returned posts, for aggregate functions
  * - having => for selecting posts based on an aggregate function
  * - where => manipulate the generated WHERE clause. Currently broken, see https://trac.habariproject.org/habari/ticket/1383
  * - add_select => an array of clauses to be added to the generated SELECT clause.
  * - fetch_fn => the function used to fetch data, one of 'get_results', 'get_row', 'get_value', 'get_query'
  *
  * Further description of parameters, including usage examples, can be found at
  * http://wiki.habariproject.org/en/Dev:Retrieving_Posts
  *
  * @return Posts|Post|string An array of Post objects, or a single post object, depending on request
  */
 public static function get($paramarray = array())
 {
     static $presets;
     $select_distinct = array();
     // If $paramarray is a string, use it as a Preset
     if (is_string($paramarray)) {
         $paramarray = array('preset' => $paramarray);
     }
     // If $paramarray is a querystring, convert it to an array
     $paramarray = Utils::get_params($paramarray);
     if ($paramarray instanceof \ArrayIterator) {
         $paramarray = $paramarray->getArrayCopy();
     }
     // If a preset is defined, get the named array and merge it with the provided parameters,
     // allowing the additional $paramarray settings to override the preset
     if (isset($paramarray['preset'])) {
         if (!isset($presets)) {
             $presets = Plugins::filter('posts_get_all_presets', $presets, $paramarray['preset']);
         }
         $paramarray = Posts::merge_presets($paramarray, $presets);
     }
     // let plugins alter the param array before we use it. could be useful for modifying search results, etc.
     $paramarray = Plugins::filter('posts_get_paramarray', $paramarray);
     $join_params = array();
     $params = array();
     $fns = array('get_results', 'get_row', 'get_value', 'get_query');
     $select_ary = array();
     // Default fields to select, everything by default
     $default_fields = Plugins::filter('post_default_fields', Post::default_fields(), $paramarray);
     if (isset($paramarray['default_fields'])) {
         $param_defaults = Utils::single_array($paramarray['default_fields']);
         $default_fields = array_merge($default_fields, $param_defaults);
     }
     foreach ($default_fields as $field => $value) {
         if (preg_match('/(?:(?P<table>[\\w\\{\\}]+)\\.)?(?P<field>\\w+)(?:(?:\\s+as\\s+)(?P<alias>\\w+))?/i', $field, $fielddata)) {
             if (empty($fielddata['table'])) {
                 $fielddata['table'] = '{posts}';
             }
             if (empty($fielddata['alias'])) {
                 $fielddata['alias'] = $fielddata['field'];
             }
         }
         $select_ary[$fielddata['alias']] = "{$fielddata['table']}.{$fielddata['field']} AS {$fielddata['alias']}";
         $select_distinct[$fielddata['alias']] = "{$fielddata['table']}.{$fielddata['field']}";
     }
     // Define the WHERE sets to process and OR in the final SQL statement
     if (isset($paramarray['where']) && is_array($paramarray['where'])) {
         $wheresets = $paramarray['where'];
     } else {
         $wheresets = array(array());
     }
     /* Start building the WHERE clauses */
     $query = Query::create('{posts}');
     $query->select($select_ary);
     // If the request has a textual WHERE clause, add it to the query then continue the processing of the $wheresets
     if (isset($paramarray['where']) && is_string($paramarray['where'])) {
         $query->where()->add($paramarray['where']);
     }
     foreach ($wheresets as $paramset) {
         $where = new QueryWhere();
         $paramset = array_merge((array) $paramarray, (array) $paramset);
         if (isset($paramset['id'])) {
             $where->in('{posts}.id', $paramset['id'], 'posts_id', 'intval');
         }
         if (isset($paramset['not:id'])) {
             $where->in('{posts}.id', $paramset['not:id'], 'posts_not_id', 'intval', false);
         }
         if (isset($paramset['status']) && !self::empty_param($paramset['status'])) {
             $where->in('{posts}.status', $paramset['status'], 'posts_status', function ($a) {
                 return Post::status($a);
             });
         }
         if (isset($paramset['not:status']) && !self::empty_param($paramset['not:status'])) {
             $where->in('{posts}.status', $paramset['not:status'], 'posts_not_status', function ($a) {
                 return Post::status($a);
             }, null, false);
         }
         if (isset($paramset['content_type']) && !self::empty_param($paramset['content_type'])) {
             $where->in('{posts}.content_type', $paramset['content_type'], 'posts_content_type', function ($a) {
                 return Post::type($a);
             });
         }
         if (isset($paramset['not:content_type'])) {
             $where->in('{posts}.content_type', $paramset['not:content_type'], 'posts_not_content_type', function ($a) {
                 return Post::type($a);
             }, false);
         }
         if (isset($paramset['slug'])) {
             $where->in('{posts}.slug', $paramset['slug'], 'posts_slug');
         }
         if (isset($paramset['not:slug'])) {
             $where->in('{posts}.slug', $paramset['not:slug'], 'posts_not_slug', null, false);
         }
         if (isset($paramset['user_id']) && 0 !== $paramset['user_id']) {
             $where->in('{posts}.user_id', $paramset['user_id'], 'posts_user_id', 'intval');
         }
         if (isset($paramset['not:user_id']) && 0 !== $paramset['not:user_id']) {
             $where->in('{posts}.user_id', $paramset['not:user_id'], 'posts_not_user_id', 'intval', false);
         }
         if (isset($paramset['vocabulary'])) {
             if (is_string($paramset['vocabulary'])) {
                 $paramset['vocabulary'] = Utils::get_params($paramset['vocabulary']);
             }
             // parse out the different formats we accept arguments in into a single mutli-dimensional array of goodness
             $paramset['vocabulary'] = self::vocabulary_params($paramset['vocabulary']);
             $object_id = Vocabulary::object_type_id('post');
             if (isset($paramset['vocabulary']['all'])) {
                 $all = $paramset['vocabulary']['all'];
                 foreach ($all as $vocab => $value) {
                     foreach ($value as $field => $terms) {
                         // we only support these fields to search by
                         if (!in_array($field, array('id', 'term', 'term_display'))) {
                             continue;
                         }
                         $join_group = Query::new_param_name('join');
                         $query->join('JOIN {object_terms} ' . $join_group . '_ot ON {posts}.id = ' . $join_group . '_ot.object_id', array(), 'term2post_posts_' . $join_group);
                         $query->join('JOIN {terms} ' . $join_group . '_t ON ' . $join_group . '_ot.term_id = ' . $join_group . '_t.id', array(), 'terms_term2post_' . $join_group);
                         $query->join('JOIN {vocabularies} ' . $join_group . '_v ON ' . $join_group . '_t.vocabulary_id = ' . $join_group . '_v.id', array(), 'terms_vocabulary_' . $join_group);
                         $where->in($join_group . '_v.name', $vocab);
                         $where->in($join_group . "_t.{$field}", $terms);
                         $where->in($join_group . '_ot.object_type_id', $object_id);
                     }
                     // this causes no posts to match if combined with 'any' below and should be re-thought... somehow
                     $groupby = implode(',', $select_distinct);
                     $having = 'count(*) = ' . count($terms);
                     // @todo this seems like it's in the wrong place
                 }
             }
             if (isset($paramset['vocabulary']['any'])) {
                 $any = $paramset['vocabulary']['any'];
                 $orwhere = new QueryWhere('OR');
                 foreach ($any as $vocab => $value) {
                     foreach ($value as $field => $terms) {
                         $andwhere = new QueryWhere();
                         // we only support these fields to search by
                         if (!in_array($field, array('id', 'term', 'term_display'))) {
                             continue;
                         }
                         $join_group = Query::new_param_name('join');
                         $query->join('JOIN {object_terms} ' . $join_group . '_ot ON {posts}.id = ' . $join_group . '_ot.object_id', array(), 'term2post_posts_' . $join_group);
                         $query->join('JOIN {terms} ' . $join_group . '_t ON ' . $join_group . '_ot.term_id = ' . $join_group . '_t.id', array(), 'terms_term2post_' . $join_group);
                         $query->join('JOIN {vocabularies} ' . $join_group . '_v ON ' . $join_group . '_t.vocabulary_id = ' . $join_group . '_v.id', array(), 'terms_vocabulary_' . $join_group);
                         $andwhere->in($join_group . '_v.name', $vocab);
                         $andwhere->in($join_group . "_t.{$field}", $terms);
                         $andwhere->in($join_group . '_ot.object_type_id', $object_id);
                     }
                     $orwhere->add($andwhere);
                     // @todo this seems like it's in the wrong place
                 }
                 $where->add($orwhere);
             }
             if (isset($paramset['vocabulary']['not'])) {
                 $not = $paramset['vocabulary']['not'];
                 foreach ($not as $vocab => $value) {
                     foreach ($value as $field => $terms) {
                         // we only support these fields to search by
                         if (!in_array($field, array('id', 'term', 'term_display'))) {
                             continue;
                         }
                         $subquery_alias = Query::new_param_name('subquery');
                         $subquery = Query::create('{object_terms}')->select('object_id');
                         $subquery->join('JOIN {terms} ON {terms}.id = {object_terms}.term_id');
                         $subquery->join('JOIN {vocabularies} ON {terms}.vocabulary_id = {vocabularies}.id');
                         $subquery->where()->in("{terms}.{$field}", $terms);
                         $subquery->where()->in('{object_terms}.object_type_id', $object_id);
                         $subquery->where()->in('{vocabularies}.name', $vocab);
                         $query->join('LEFT JOIN (' . $subquery->get() . ') ' . $subquery_alias . ' ON ' . $subquery_alias . '.object_id = {posts}.id', $subquery->params(), $subquery_alias);
                         $where->add('COALESCE(' . $subquery_alias . '.object_id, 0) = 0');
                     }
                 }
             }
         }
         if (isset($paramset['criteria'])) {
             // this regex matches any unicode letters (\p{L}) or numbers (\p{N}) inside a set of quotes (but strips the quotes) OR not in a set of quotes
             preg_match_all('/(?<=")([\\p{L}\\p{N}]+[^"]*)(?=")|([\\p{L}\\p{N}]+)/u', $paramset['criteria'], $matches);
             foreach ($matches[0] as $word) {
                 $crit_placeholder = $query->new_param_name('criteria');
                 $where->add("( LOWER( {posts}.title ) LIKE :{$crit_placeholder} OR LOWER( {posts}.content ) LIKE :{$crit_placeholder})", array($crit_placeholder => '%' . MultiByte::strtolower($word) . '%'));
             }
         }
         if (isset($paramset['title'])) {
             $where->add("LOWER( {posts}.title ) LIKE :title_match", array('title_match' => MultiByte::strtolower($paramset['title'])));
         }
         if (isset($paramset['title_search'])) {
             // this regex matches any unicode letters (\p{L}) or numbers (\p{N}) inside a set of quotes (but strips the quotes) OR not in a set of quotes
             preg_match_all('/(?<=")([\\p{L}\\p{N}]+[^"]*)(?=")|([\\p{L}\\p{N}]+)/u', $paramset['title_search'], $matches);
             foreach ($matches[0] as $word) {
                 $crit_placeholder = $query->new_param_name('title_search');
                 $where->add("LOWER( {posts}.title ) LIKE :{$crit_placeholder}", array($crit_placeholder => '%' . MultiByte::strtolower($word) . '%'));
             }
         }
         // Handle field queries on posts and joined tables
         foreach ($select_ary as $field => $aliasing) {
             if (in_array($field, array('id', 'title', 'slug', 'status', 'content_type', 'user_id'))) {
                 // skip fields that we're handling a different way
                 continue;
             }
             if (isset($paramset[$field])) {
                 if (is_callable($paramset[$field])) {
                     $paramset[$field]($where, $paramset);
                 } else {
                     $where->in($field, $paramset[$field], 'posts_field_' . $field);
                 }
             }
         }
         //Done
         if (isset($paramset['all:info']) || isset($paramset['info'])) {
             // merge the two possibile calls together
             $infos = array_merge(isset($paramset['all:info']) ? $paramset['all:info'] : array(), isset($paramset['info']) ? $paramset['info'] : array());
             if (Utils::is_traversable($infos)) {
                 $pi_count = 0;
                 foreach ($infos as $info_key => $info_value) {
                     $pi_count++;
                     $infokey_field = Query::new_param_name('info_key');
                     $infovalue_field = Query::new_param_name('info_value');
                     $query->join("LEFT JOIN {postinfo} ipi{$pi_count} ON {posts}.id = ipi{$pi_count}.post_id AND ipi{$pi_count}.name = :{$infokey_field} AND ipi{$pi_count}.value = :{$infovalue_field}", array($infokey_field => $info_key, $infovalue_field => $info_value), 'all_info_' . $info_key);
                     $where->add("ipi{$pi_count}.name <> ''");
                     $query->select(array("info_{$info_key}_value" => "ipi{$pi_count}.value AS info_{$info_key}_value"));
                     $select_distinct["info_{$info_key}_value"] = "info_{$info_key}_value";
                 }
             }
         }
         //Done
         if (isset($paramset['any:info'])) {
             if (Utils::is_traversable($paramset['any:info'])) {
                 $pi_count = 0;
                 $orwhere = new QueryWhere('OR');
                 foreach ($paramset['any:info'] as $info_key => $info_value) {
                     $pi_count++;
                     if (is_array($info_value)) {
                         $infokey_field = Query::new_param_name('info_key');
                         $inwhere = new QueryWhere('');
                         $inwhere->in("aipi{$pi_count}.value", $info_value);
                         $query->join("LEFT JOIN {postinfo} aipi{$pi_count} ON {posts}.id = aipi{$pi_count}.post_id AND aipi{$pi_count}.name = :{$infokey_field} AND " . $inwhere->get(), array_merge(array($info_key), $inwhere->params()), 'any_info_' . $info_key);
                     } else {
                         $infokey_field = Query::new_param_name('info_key');
                         $infovalue_field = Query::new_param_name('info_value');
                         $query->join("LEFT JOIN {postinfo} aipi{$pi_count} ON {posts}.id = aipi{$pi_count}.post_id AND aipi{$pi_count}.name = :{$infokey_field} AND aipi{$pi_count}.value = :{$infovalue_field}", array($infokey_field => $info_key, $infovalue_field => $info_value), 'any_info_' . $info_key);
                     }
                     $orwhere->add("aipi{$pi_count}.name <> ''");
                     $query->select(array("info_{$info_key}_value" => "aipi{$pi_count}.value AS info_{$info_key}_value"));
                     $select_distinct["info_{$info_key}_value"] = "info_{$info_key}_value";
                 }
                 $where->add('(' . $orwhere->get() . ')');
             }
         }
         // Done
         if (isset($paramset['has:info'])) {
             $has_info = Utils::single_array($paramset['has:info']);
             $pi_count = 0;
             $orwhere = new QueryWhere('OR');
             foreach ($has_info as $info_name) {
                 $infoname_field = Query::new_param_name('info_name');
                 $pi_count++;
                 $query->join("LEFT JOIN {postinfo} hipi{$pi_count} ON {posts}.id = hipi{$pi_count}.post_id AND hipi{$pi_count}.name = :{$infoname_field}", array($infoname_field => $info_name), 'has_info_' . $info_name);
                 $orwhere->add("hipi{$pi_count}.name <> ''");
                 $query->select(array("info_{$info_name}_value" => "hipi{$pi_count}.value AS info_{$info_name}_value"));
                 $select_distinct["info_{$info_name}_value"] = "info_{$info_name}_value";
             }
             $where->add('(' . $orwhere->get() . ')');
         }
         //Done
         if (isset($paramset['not:all:info']) || isset($paramset['not:info'])) {
             // merge the two possible calls together
             $infos = array_merge(isset($paramset['not:all:info']) ? $paramset['not:all:info'] : array(), isset($paramset['not:info']) ? $paramset['not:info'] : array());
             if (Utils::is_traversable($infos)) {
                 $orwhere = new QueryWhere('OR');
                 foreach ($infos as $info_key => $info_value) {
                     $andwhere = new QueryWhere();
                     $andwhere->in('{postinfo}.name', $info_key);
                     $andwhere->in('{postinfo}.value', $info_value);
                     $orwhere->add($andwhere);
                 }
                 // see that hard-coded number in having()? sqlite wets itself if we use a bound parameter... don't change that
                 $subquery = Query::create('{postinfo}')->select('{postinfo}.post_id')->groupby('post_id')->having('COUNT(*) = ' . count($infos));
                 $subquery->where()->add($orwhere);
                 $where->in('{posts}.id', $subquery, 'posts_not_all_info_query', null, false);
             }
         }
         //Tested. Test fails with original code
         if (isset($paramset['not:any:info'])) {
             if (Utils::is_traversable($paramset['not:any:info'])) {
                 $subquery = Query::create('{postinfo}')->select('post_id');
                 foreach ($paramset['not:any:info'] as $info_key => $info_value) {
                     $infokey_field = $query->new_param_name('info_key');
                     $infovalue_field = $query->new_param_name('info_value');
                     //							$subquery->where()->add(" ({postinfo}.name = :{$infokey_field} AND {postinfo}.value = :{$infovalue_field} ) ", array($infokey_field => $info_key, $infovalue_field => $info_value));
                     $subquery->where('OR')->add(" ({postinfo}.name = :{$infokey_field} AND {postinfo}.value = :{$infovalue_field} ) ", array($infokey_field => $info_key, $infovalue_field => $info_value));
                 }
                 $where->in('{posts}.id', $subquery, 'posts_not_any_info', null, false);
             }
         }
         /**
          * Build the statement needed to filter by pubdate:
          * If we've got the day, then get the date;
          * If we've got the month, but no date, get the month;
          * If we've only got the year, get the whole year.
          */
         if (isset($paramset['day']) && isset($paramset['month']) && isset($paramset['year'])) {
             $start_date = sprintf('%d-%02d-%02d', $paramset['year'], $paramset['month'], $paramset['day']);
             $start_date = DateTime::create($start_date);
             $where->add('pubdate BETWEEN :start_date AND :end_date', array('start_date' => $start_date->sql, 'end_date' => $start_date->modify('+1 day -1 second')->sql));
         } elseif (isset($paramset['month']) && isset($paramset['year'])) {
             $start_date = sprintf('%d-%02d-%02d', $paramset['year'], $paramset['month'], 1);
             $start_date = DateTime::create($start_date);
             $where->add('pubdate BETWEEN :start_date AND :end_date', array('start_date' => $start_date->sql, 'end_date' => $start_date->modify('+1 month -1 second')->sql));
         } elseif (isset($paramset['year'])) {
             $start_date = sprintf('%d-%02d-%02d', $paramset['year'], 1, 1);
             $start_date = DateTime::create($start_date);
             $where->add('pubdate BETWEEN :start_date AND :end_date', array('start_date' => $start_date->sql, 'end_date' => $start_date->modify('+1 year -1 second')->sql));
         }
         if (isset($paramset['after'])) {
             $where->add('pubdate > :after_date', array('after_date' => DateTime::create($paramset['after'])->sql));
         }
         if (isset($paramset['before'])) {
             $where->add('pubdate < :before_date', array('before_date' => DateTime::create($paramset['before'])->sql));
         }
         // Concatenate the WHERE clauses
         $query->where()->add($where);
     }
     if (isset($paramset['post_join'])) {
         $post_joins = Utils::single_array($paramset['post_join']);
         foreach ($post_joins as $post_join) {
             if (preg_match('#^(\\S+)(?:\\s+as)?\\s+(\\S+)$#i', $post_join, $matches)) {
                 $query->join("LEFT JOIN {$matches[1]} {$matches[2]} ON {$matches[2]}.post_id = {posts}.id ");
             } else {
                 $query->join("LEFT JOIN {$post_join} ON {$post_join}.post_id = {posts}.id ");
             }
         }
     }
     // Only show posts to which the current user has permission
     if (isset($paramset['ignore_permissions'])) {
         $master_perm_where = new QueryWhere();
         // Set up the merge params
         $merge_params = array($join_params, $params);
         $params = call_user_func_array('array_merge', $merge_params);
     } else {
         $master_perm_where = new QueryWhere();
         // This set of wheres will be used to generate a list of post_ids that this user can read
         $perm_where = new QueryWhere('OR');
         $perm_where_denied = new QueryWhere('AND');
         // Get the tokens that this user is granted or denied access to read
         $read_tokens = isset($paramset['read_tokens']) ? $paramset['read_tokens'] : ACL::user_tokens(User::identify(), 'read', true);
         $deny_tokens = isset($paramset['deny_tokens']) ? $paramset['deny_tokens'] : ACL::user_tokens(User::identify(), 'deny', true);
         // If a user can read any post type, let him
         if (User::identify()->can('post_any', 'read')) {
             $perm_where->add('(1=1)');
         } else {
             // If a user can read his own posts, let him
             if (User::identify()->can('own_posts', 'read')) {
                 $perm_where->add('{posts}.user_id = :current_user_id', array('current_user_id' => User::identify()->id));
             }
             // If a user can read specific post types, let him
             $permitted_post_types = array();
             foreach (Post::list_active_post_types() as $name => $posttype) {
                 if (User::identify()->can('post_' . Utils::slugify($name), 'read')) {
                     $permitted_post_types[] = $posttype;
                 }
             }
             if (count($permitted_post_types) > 0) {
                 $perm_where->in('{posts}.content_type', $permitted_post_types, 'posts_permitted_types', 'intval');
             }
             // If a user can read posts with specific tokens, let him
             if (count($read_tokens) > 0) {
                 $query->join('LEFT JOIN {post_tokens} pt_allowed ON {posts}.id= pt_allowed.post_id AND pt_allowed.token_id IN (' . implode(',', $read_tokens) . ')', array(), 'post_tokens__allowed');
                 $perm_where->add('pt_allowed.post_id IS NOT NULL', array(), 'perms_join_not_null');
             }
             // If a user has access to read other users' unpublished posts, let him
             if (User::identify()->can('post_unpublished', 'read')) {
                 $perm_where->add('({posts}.status <> :status_published AND {posts}.user_id <> :current_user_id)', array('current_user_id' => User::identify()->id, 'status_published' => Post::status('published')));
             }
         }
         // If a user is denied access to all posts, do so
         if (User::identify()->cannot('post_any')) {
             $perm_where_denied->add('(1=0)');
         } else {
             // If a user is denied read access to specific post types, deny him
             $denied_post_types = array();
             foreach (Post::list_active_post_types() as $name => $posttype) {
                 if (User::identify()->cannot('post_' . Utils::slugify($name))) {
                     $denied_post_types[] = $posttype;
                 }
             }
             if (count($denied_post_types) > 0) {
                 $perm_where_denied->in('{posts}.content_type', $denied_post_types, 'posts_denied_types', 'intval', false);
             }
             // If a user is denied read access to posts with specific tokens, deny it
             if (count($deny_tokens) > 0) {
                 $query->join('LEFT JOIN {post_tokens} pt_denied ON {posts}.id= pt_denied.post_id AND pt_denied.token_id IN (' . implode(',', $deny_tokens) . ')', array(), 'post_tokens__denied');
                 $perm_where_denied->add('pt_denied.post_id IS NULL', array(), 'perms_join_null');
             }
             // If a user is denied access to read other users' unpublished posts, deny it
             if (User::identify()->cannot('post_unpublished')) {
                 $perm_where_denied->add('({posts}.status = :status_published OR {posts}.user_id = :current_user_id)', array('current_user_id' => User::identify()->id, 'status_published' => Post::status('published')));
             }
         }
         Plugins::act('post_get_perm_where', $perm_where, $paramarray);
         Plugins::act('post_get_perm_where_denied', $perm_where_denied, $paramarray);
         // If there are granted permissions to check, add them to the where clause
         if ($perm_where->count() == 0 && !$query->joined('post_tokens__allowed')) {
             $master_perm_where->add('(1=0)', array(), 'perms_granted');
         } else {
             $master_perm_where->add($perm_where, array(), 'perms_granted');
         }
         // If there are denied permissions to check, add them to the where clause
         if ($perm_where_denied->count() > 0 || $query->joined('post_tokens__denied')) {
             $master_perm_where->add($perm_where_denied, array(), 'perms_denied');
         }
     }
     $query->where()->add($master_perm_where, array(), 'master_perm_where');
     // Extract the remaining parameters which will be used onwards
     // For example: page number, fetch function, limit
     $paramarray = new SuperGlobal($paramarray);
     $extract = $paramarray->filter_keys('page', 'fetch_fn', 'count', 'orderby', 'groupby', 'limit', 'offset', 'nolimit', 'having', 'add_select');
     foreach ($extract as $key => $value) {
         ${$key} = $value;
     }
     // Calculate the OFFSET based on the page number. Requires a limit.
     if (isset($page) && is_numeric($page) && !isset($paramset['offset']) && isset($limit)) {
         $offset = (intval($page) - 1) * intval($limit);
     }
     /**
      * Determine which fetch function to use:
      * If it is specified, make sure it is valid (based on the $fns array defined at the beginning of this function);
      * Else, use 'get_results' which will return a Posts array of Post objects.
      */
     if (isset($fetch_fn)) {
         if (!in_array($fetch_fn, $fns)) {
             $fetch_fn = $fns[0];
         }
     } else {
         $fetch_fn = $fns[0];
     }
     // Add arbitrary fields to the select clause for sorting and output
     if (isset($add_select)) {
         $query->select($add_select);
     }
     /**
      * If a count is requested:
      * Replace the current fields to select with a COUNT();
      * Change the fetch function to 'get_value';
      * Remove the ORDER BY since it's useless.
      * Remove the GROUP BY (tag search added it)
      */
     if (isset($count)) {
         $query->set_select("COUNT({$count})");
         $fetch_fn = isset($paramarray['fetch_fn']) ? $fetch_fn : 'get_value';
         $orderby = null;
         $groupby = null;
         $having = null;
     }
     // If the month counts are requested, replaced the select clause
     if (isset($paramset['month_cts'])) {
         if (isset($paramset['vocabulary'])) {
             $query->set_select('MONTH(FROM_UNIXTIME(pubdate)) AS month, YEAR(FROM_UNIXTIME(pubdate)) AS year, COUNT(DISTINCT {posts}.id) AS ct');
         } else {
             $query->set_select('MONTH(FROM_UNIXTIME(pubdate)) AS month, YEAR(FROM_UNIXTIME(pubdate)) AS year, COUNT(*) AS ct');
         }
         $groupby = 'year, month';
         if (!isset($paramarray['orderby'])) {
             $orderby = 'year, month';
         }
     }
     // Remove the LIMIT if 'nolimit'
     // Doing this first should allow OFFSET to work
     if (isset($nolimit)) {
         $limit = null;
     }
     // Define the LIMIT, OFFSET, ORDER BY, GROUP BY if they exist
     if (isset($limit)) {
         $query->limit($limit);
     }
     if (isset($offset)) {
         $query->offset($offset);
     }
     if (isset($orderby)) {
         $query->orderby($orderby);
     }
     if (isset($groupby)) {
         $query->groupby($groupby);
     }
     if (isset($having)) {
         $query->having($having);
     }
     if (isset($paramarray['on_query_built'])) {
         foreach (Utils::single_array($paramarray['on_query_built']) as $built) {
             $built($query);
         }
     }
     Plugins::act('posts_get_query', $query, $paramarray);
     /* All SQL parts are constructed, on to real business! */
     /**
      * DEBUG: Uncomment the following line to display everything that happens in this function
      */
     //print_R('<pre>'.$query.'</pre>');
     //Utils::debug( $paramarray, $fetch_fn, $query, $params );
     //Session::notice($query);
     if ('get_query' == $fetch_fn) {
         return array($query->get(), $query->params());
     }
     /**
      * Execute the SQL statement using the PDO extension
      */
     DB::set_fetch_mode(\PDO::FETCH_CLASS);
     $fetch_class = 'Post';
     if (isset($paramarray['fetch_class'])) {
         $fetch_class = $paramarray['fetch_class'];
     }
     DB::set_fetch_class($fetch_class);
     $results = DB::$fetch_fn($query->get(), $query->params(), $fetch_class);
     //Utils::debug($results, $query->get(), $query->params());
     //Utils::debug( $paramarray, $fetch_fn, $query->get(), $query->params(), $results );
     //var_dump( $query );
     /**
      * Return the results
      */
     if ('get_results' != $fetch_fn) {
         // Since a single result was requested, return a single Post object.
         return $results;
     } elseif (is_array($results)) {
         // With multiple results, return a Posts array of Post objects.
         $c = __CLASS__;
         $return_value = new $c($results);
         $return_value->get_param_cache = $paramarray;
         return $return_value;
     }
 }
 /**
  * Renames a category
  * If the master category exists, the categories will be merged with it.
  * If not, it will be created first.
  *
  * Adapted from Tags::rename()
  *
  * @param mixed tag The category text, slug or id to be renamed
  * @param mixed master The category to which it should be renamed, or the slug, text or id of it
  **/
 public static function rename($master, $category, $object_type = 'post')
 {
     $vocabulary = Vocabulary::get(self::$vocabulary);
     $type_id = Vocabulary::object_type_id($object_type);
     // get the term to be renamed
     $term = $vocabulary->get_term($category);
     // get the master term
     $master_term = $vocabulary->get_term($master);
     // check if it already exists
     if (!isset($master_term->term)) {
         // it didn't exist, so we assume it's text and create it
         $term->term_display = $master;
         $term->term = $master;
         $term->update();
         // that's it, we're done.
         EventLog::log(_t('Category %s has been renamed to %s.', array($category, $master), 'simplecategories'), 'info', 'category', 'simplecategories');
     } else {
         if (!$master_term->is_descendant_of($term)) {
             $posts = array();
             $posts = Posts::get(array('vocabulary' => array('any' => array($term), 'not' => array($master_term)), 'nolimit' => true));
             // categorize all the $category Posts as $master
             foreach ($posts as $post) {
                 //				$vocabulary->set_object_terms( 'post', $post->id, $master );
                 $master_term->associate('post', $post->id);
             }
             // move the old $term's children over to $master_term
             foreach ($term->children() as $child) {
                 // is this needed?
                 //				$child = $vocabulary->get_term( $child->id );
                 $vocabulary->move_term($child, $master_term);
             }
             // delete the old $term and all its associations
             self::delete_category($term->id);
             EventLog::log(_t('Category %s has been merged into %s.', array($category, $master), 'simplecategories'), 'info', 'category', 'simplecategories');
         } else {
             Session::notice(_t('Cannot merge %1$s into %2$s, since %2$s is a descendant of %1$s', array($term, $master), 'shelves'));
         }
     }
 }
Exemple #26
0
 /**
  * Returns the tags vocabulary
  *
  * @return Vocabulary The tags vocabulary
  */
 public static function vocabulary()
 {
     return Vocabulary::get(self::$vocabulary);
 }
/**
 * this is for importing a list of value vocabulary files.
 *
 * it's designed specifically to import the list of marc21 VES files,
 * but may be modified and expanded to support more things
 *
 * @param $task
 * @param $args
 *
 * @throws Exception
 */
function run_import_list($task, $args)
{
    xdebug_break();

    //check the argument counts
    //check the argument counts
    if (count($args) < 1) {
        throw new Exception('You must provide a vocabulary type.');
    }

    if (count($args) < 2) {
        throw new Exception('You must provide a file name.');
    }

    //set the arguments
    $type     = strtolower($args[0]);
    $filePath = $args[1];
    $batchId =  $args[3];

    //does the file exist?
    if (! file_exists($filePath)) {
        throw new Exception('You must supply a valid file to import');
    }

    //is the file a valid type?
    if (preg_match('/^.+\.([[:alpha:]]{2,4})$/', $filePath, $matches)) {
        if (! in_array(
          strtolower($matches[1]),
          array(
            "json",
            "rdf",
            "csv",
            "xml"
          )
        )
        ) {
            throw new Exception('You must provide a valid file type based on the extension');
        }
    } else {
        throw new Exception("File type cannot be determined from the file extension");
    }

    /************************************************************
     *    Set Defaults Here                                      *
     *************************************************************/
    $fileType    = $matches[1];
    //todo: need to figure out a way to pass defaults dynamically

    $importTask = new pakeTask('import-vocabulary');

    //     parse file to get the fields/columns and data
    $file = fopen($filePath, "r");
    if (! $file) {
        throw new Exception("Can't read supplied file");
    }

    switch ($fileType) {
        case "csv":
            try {
                $reader = new aCsvReader($filePath);
            } catch(Exception $e) {
                throw new Exception("Not a happy CSV file! Error: " . $e);
            }
            $uploadPath = $GLOBALS['uploadPath'];
            ;
            if ('vocab' == $type) {
                // Get array of heading names found
                $headings = $reader->getHeadings();
                $fields   = VocabularyPeer::getFieldNames();

                try {
                    while ($row = $reader->getRow()) {
                        //        lookup the URI (or the OMR ID if available) for a match
                        if (empty($row["VES"])) {
                            //skip this one
                            break;
                        }

                        $uri        = $baseDomain . $row["VES"] . "#";
                        $vocab      = VocabularyPeer::getVocabularyByUri($uri);
                        $updateTime = time();

                        if (! $vocab) {
                            //          create a new concept or element
                            $vocab = new Vocabulary();
                            $vocab->setUri($uri);
                            $vocab->setCreatedAt($updateTime);
                            $vocab->setCreatedUserId($userId);
                            $vocab->setAgentId($agentID);
                            $vocab->setBaseDomain($baseDomain);
                            $vocab->setCommunity("Libraries, MARC21");
                            $vocab->setLanguage("en");
                            $vocab->setStatusId(1);
                        } else {
                            $vocab->setLastUpdated($updateTime);
                            $vocab->setUpdatedUserId($userId);
                        }

                        $vocab->setName(fixEncoding(rtrim($row['Name'])));
                        $vocab->setNote(fixEncoding(rtrim($row['Note'])));
                        $vocab->setToken($row['VES']);
                        $vocab->save();

                        //type
                        $args[0] = "vocab";
                        //vocabid
                        $args[2] = $vocab->getId();
                        //filepath
                        $args[1] = $GLOBALS['uploadPath'] . $row['VES'] . ".csv";
                        $args[3] = $batchId;
                        $args[4] = "-d";

                        run_import_vocabulary($importTask, $args);
                        $foo = $vocab->countConcepts();
                    }
                } catch(Exception $e) {
                    throw new Exception($e);
                }
            } else //it's a schema
            {
                try {
                    while ($row = $reader->getRow()) {

                        //NOTE: this is explicitly tuned to a particular import file
                        //TODO: generalize this import mapping

                        // lookup the URI (or the OMR ID if available) for a match
                        if (empty($row["URI"])) {
                            //skip this one
                            break;
                        }

                        $uri        = $row["URI"];
                        $schema     = SchemaPeer::getschemaByUri($uri);
                        $updateTime = time();

                        if (! $schema) {
                            //  create a new vocabulary
                            $schema = new Schema();
                            $schema->setUri($uri);
                            $schema->setCreatedAt($updateTime);
                            $schema->setCreatedUserId($userId);
                            $schema->setAgentId($agentID);
                            $schema->setBaseDomain($baseDomain);
                            $schema->setProfileId(1);
                        } else {
                            $schema->setUpdatedAt($updateTime);
                            $schema->setUpdatedUserId($userId);
                        }

                        $schema->setCommunity($row['Tags']);
                        $schema->setLanguage($row['Language']);
                        $schema->setNsType("slash");
                        $schema->setName($row['Label']);
                        $schema->setNote($row['Note']);
                        $schema->setStatusId(1);
                        $schema->setToken($row['Name']);
                        $schema->setUrl($row['URL']);
                        $schema->save();

                        //todo: create a new import batch here and pass it to the import args
                        //see importVocabulary->saveresults()
                        //$batchId =
                        //type
                        $args[0] = "schema";
                        //filepath
                        $args[1] = $GLOBALS['uploadPath'] . $row['File Name'];
                        //vocabid
                        $args[2] = $schema->getId();
                        $args[3] = $batchId;
                        $args[4] = "-d";

                        run_import_vocabulary($importTask, $args);
                        $foo = $schema->countSchemaPropertys();
                    }
                } catch(Exception $e) {
                    throw new Exception($e);
                }
            }
            break;
        default:
    }
}
Exemple #28
0
 private function upgrade_db_post_3749()
 {
     $type_id = Vocabulary::object_type_id('post');
     $vocabulary = Vocabulary::create(array('name' => 'tags', 'description' => 'Habari\'s tags implementation', 'features' => array('multiple', 'free')));
     $new_tag = null;
     $post_ids = array();
     $prefix = Config::get('db_connection')->prefix;
     $results = DB::get_results("SELECT id, tag_text, tag_slug from {$prefix}tags");
     foreach ($results as $tag) {
         $new_tag = $vocabulary->add_term($tag->tag_text);
         $post_ids = DB::get_column("SELECT post_id FROM {$prefix}tag2post WHERE tag_id = ?", array($tag->id));
         foreach ($post_ids as $id) {
             DB::insert("{object_terms}", array('term_id' => $new_tag->id, 'object_id' => $id, 'object_type_id' => $type_id));
         }
     }
 }
Exemple #29
0
    /**
     * Returns a post or posts based on supplied parameters.
     * <b>THIS CLASS SHOULD CACHE QUERY RESULTS!</b>
     *
     * @param array $paramarry An associated array of parameters, or a querystring
     * @return array An array of Post objects, or a single post object, depending on request
     */
    public static function get($paramarray = array())
    {
        $join_params = array();
        $params = array();
        $fns = array('get_results', 'get_row', 'get_value');
        $select_ary = array();
        // Default fields to select, everything by default
        foreach (Post::default_fields() as $field => $value) {
            $select_ary[$field] = "{posts}.{$field} AS {$field}";
        }
        // Default parameters
        $orderby = 'pubdate DESC';
        // If $paramarray is a querystring, convert it to an array
        $paramarray = Utils::get_params($paramarray);
        // Define the WHERE sets to process and OR in the final SQL statement
        if (isset($paramarray['where']) && is_array($paramarray['where'])) {
            $wheresets = $paramarray['where'];
        } else {
            $wheresets = array(array());
        }
        /* Start building the WHERE clauses */
        $wheres = array();
        $joins = array();
        // If the request as a textual WHERE clause, skip the processing of the $wheresets since it's empty
        if (isset($paramarray['where']) && is_string($paramarray['where'])) {
            $wheres[] = $paramarray['where'];
        } else {
            foreach ($wheresets as $paramset) {
                // Safety mechanism to prevent empty queries
                $where = array();
                $paramset = array_merge((array) $paramarray, (array) $paramset);
                // $nots= preg_grep( '%^not:(\w+)$%iu', (array) $paramset );
                if (isset($paramset['id'])) {
                    if (is_array($paramset['id'])) {
                        array_walk($paramset['id'], create_function('&$a,$b', '$a = intval($a);'));
                        $where[] = "{posts}.id IN (" . implode(',', array_fill(0, count($paramset['id']), '?')) . ")";
                        $params = array_merge($params, $paramset['id']);
                    } else {
                        $where[] = "{posts}.id = ?";
                        $params[] = (int) $paramset['id'];
                    }
                }
                if (isset($paramset['not:id'])) {
                    if (is_array($paramset['not:id'])) {
                        array_walk($paramset['not:id'], create_function('&$a,$b', '$a = intval($a);'));
                        $where[] = "{posts}.id NOT IN (" . implode(',', array_fill(0, count($paramset['not:id']), '?')) . ")";
                        $params = array_merge($params, $paramset['not:id']);
                    } else {
                        $where[] = "{posts}.id != ?";
                        $params[] = (int) $paramset['not:id'];
                    }
                }
                if (isset($paramset['status']) && $paramset['status'] != 'any' && 0 !== $paramset['status']) {
                    if (is_array($paramset['status'])) {
                        // remove 'any' from the list if we have an array
                        $paramset['status'] = array_diff($paramset['status'], array('any'));
                        array_walk($paramset['status'], create_function('&$a,$b', '$a = Post::status($a);'));
                        $where[] = "{posts}.status IN (" . implode(',', array_fill(0, count($paramset['status']), '?')) . ")";
                        $params = array_merge($params, $paramset['status']);
                    } else {
                        $where[] = "{posts}.status = ?";
                        $params[] = (int) Post::status($paramset['status']);
                    }
                }
                if (isset($paramset['content_type']) && $paramset['content_type'] != 'any' && 0 !== $paramset['content_type']) {
                    if (is_array($paramset['content_type'])) {
                        // remove 'any' from the list if we have an array
                        $paramset['content_type'] = array_diff($paramset['content_type'], array('any'));
                        array_walk($paramset['content_type'], create_function('&$a,$b', '$a = Post::type($a);'));
                        $where[] = "{posts}.content_type IN (" . implode(',', array_fill(0, count($paramset['content_type']), '?')) . ")";
                        $params = array_merge($params, $paramset['content_type']);
                    } else {
                        $where[] = "{posts}.content_type = ?";
                        $params[] = (int) Post::type($paramset['content_type']);
                    }
                }
                if (isset($paramset['not:content_type'])) {
                    if (is_array($paramset['not:content_type'])) {
                        array_walk($paramset['not:content_type'], create_function('&$a,$b', '$a = Post::type($a);'));
                        $where[] = "{posts}.content_type NOT IN (" . implode(',', array_fill(0, count($paramset['not:content_type']), '?')) . ")";
                        $params = array_merge($params, $paramset['not:content_type']);
                    } else {
                        $where[] = "{posts}.content_type != ?";
                        $params[] = (int) Post::type($paramset['not:content_type']);
                    }
                }
                if (isset($paramset['slug'])) {
                    if (is_array($paramset['slug'])) {
                        $where[] = "{posts}.slug IN (" . implode(',', array_fill(0, count($paramset['slug']), '?')) . ")";
                        $params = array_merge($params, $paramset['slug']);
                    } else {
                        $where[] = "{posts}.slug = ?";
                        $params[] = (string) $paramset['slug'];
                    }
                }
                if (isset($paramset['user_id']) && 0 !== $paramset['user_id']) {
                    if (is_array($paramset['user_id'])) {
                        array_walk($paramset['user_id'], create_function('&$a,$b', '$a = intval($a);'));
                        $where[] = "{posts}.user_id IN (" . implode(',', array_fill(0, count($paramset['user_id']), '?')) . ")";
                        $params = array_merge($params, $paramset['user_id']);
                    } else {
                        $where[] = "{posts}.user_id = ?";
                        $params[] = (int) $paramset['user_id'];
                    }
                }
                if (isset($paramset['tag']) || isset($paramset['tag_slug'])) {
                    $joins['tag2post_posts'] = ' JOIN {object_terms} ON {posts}.id = {object_terms}.object_id';
                    $joins['tags_tag2post'] = ' JOIN {terms} ON {object_terms}.term_id = {terms}.id';
                    if (isset($paramset['tag'])) {
                        if (is_array($paramset['tag'])) {
                            $where[] = "{terms}.term_display IN (" . implode(',', array_fill(0, count($paramset['tag']), '?')) . ")" . '  AND {object_terms}.object_type_id = ?';
                            $params = array_merge($params, $paramset['tag']);
                        } else {
                            $where[] = '{terms}.term_display = ? AND {object_terms}.object_type_id = ?';
                            $params[] = (string) $paramset['tag'];
                        }
                    }
                    if (isset($paramset['tag_slug'])) {
                        if (is_array($paramset['tag_slug'])) {
                            $where[] = "{terms}.term IN (" . implode(',', array_fill(0, count($paramset['tag_slug']), '?')) . ")" . ' AND {object_terms}.object_type_id = ?';
                            $params = array_merge($params, $paramset['tag_slug']);
                        } else {
                            $where[] = '{terms}.term= ? AND {object_terms}.object_type_id = ?';
                            $params[] = (string) $paramset['tag_slug'];
                        }
                    }
                    $params[] = Vocabulary::object_type_id(Tags::object_type());
                }
                if (isset($paramset['all:tag'])) {
                    $joins['tag2post_posts'] = ' JOIN {object_terms} ON {posts}.id = {object_terms}.object_id';
                    $joins['tags_tag2post'] = ' JOIN {terms} ON {object_terms}.term_id = {terms}.id';
                    if (is_array($paramset['all:tag'])) {
                        $where[] = '{terms}.term_display IN (' . Utils::placeholder_string($paramset['all:tag']) . ')' . ' AND {object_terms}.object_type_id = ?';
                        $params = array_merge($params, $paramset['all:tag']);
                        $groupby = '{posts}.id';
                        $having = 'count(*) = ' . count($paramset['all:tag']);
                    } else {
                        // this is actually the same as plain 'tag' for a single tag search - go with it
                        $where[] = '{terms}.term_display = ? AND {object_terms}.object_type_id = ?';
                        $params[] = $paramset['all:tag'];
                    }
                    $params[] = Vocabulary::object_type_id(Tags::object_type());
                }
                if (isset($paramset['all:tag_slug'])) {
                    $joins['tag2post_posts'] = ' JOIN {object_terms} ON {posts}.id = {object_terms}.object_id';
                    $joins['tags_tag2post'] = ' JOIN {terms} ON {object_terms}.term_id = {terms}.id';
                    if (is_array($paramset['all:tag_slug'])) {
                        $where[] = '{terms}.term IN (' . Utils::placeholder_string($paramset['all:tag_slug']) . ')' . ' AND {object_terms}.object_type_id = ?';
                        $params = array_merge($params, $paramset['all:tag_slug']);
                        $groupby = '{posts}.id';
                        $having = 'count(*) = ' . count($paramset['all:tag_slug']);
                    } else {
                        // this is actually the same as plain 'tag' for a single tag search - go with it
                        $where[] = '{terms}.term = ? AND {object_terms}.object_type_id = ?';
                        $params[] = $paramset['all:tag_slug'];
                    }
                    $params[] = Vocabulary::object_type_id(Tags::object_type());
                }
                if (isset($paramset['not:tag'])) {
                    $nottag = Utils::single_array($paramset['not:tag']);
                    $where[] = 'NOT EXISTS (SELECT 1
						FROM {object_terms}
						INNER JOIN {terms} ON {terms}.id = {object_terms}.term_id
						WHERE {terms}.term_display IN (' . Utils::placeholder_string($nottag) . ')
						AND {object_terms}.object_id = {posts}.id
						AND {object_terms}.object_type_id = ?)
					';
                    $params = array_merge($params, $nottag);
                    $params[] = Vocabulary::object_type_id(Tags::object_type());
                }
                if (isset($paramset['not:tag_slug'])) {
                    $nottag = Utils::single_array($paramset['not:tag_slug']);
                    $where[] = 'NOT EXISTS (SELECT 1
						FROM {object_terms}
						INNER JOIN {terms} ON {terms}.id = {object_terms}.term_id
						WHERE {terms}.term_display IN (' . Utils::placeholder_string($nottag) . ')
						AND {object_terms}.object_id = {posts}.id
						AND {object_terms}.object_type_id = ?)
					';
                    $params = array_merge($params, $nottag);
                    $params[] = Vocabulary::object_type_id(Tags::object_type());
                }
                if (isset($paramset['criteria'])) {
                    preg_match_all('/(?<=")([\\p{L}\\p{N}]+[^"]*)(?=")|([\\p{L}\\p{N}]+)/u', $paramset['criteria'], $matches);
                    foreach ($matches[0] as $word) {
                        $where[] .= "({posts}.title LIKE CONCAT('%',?,'%') OR {posts}.content LIKE CONCAT('%',?,'%'))";
                        $params[] = $word;
                        $params[] = $word;
                        // Not a typo (there are two ? in the above statement)
                    }
                }
                if (isset($paramset['all:info']) || isset($paramset['info'])) {
                    // merge the two possibile calls together
                    $infos = array_merge(isset($paramset['all:info']) ? $paramset['all:info'] : array(), isset($paramset['info']) ? $paramset['info'] : array());
                    if (Utils::is_traversable($infos)) {
                        $pi_count = 0;
                        foreach ($infos as $info_key => $info_value) {
                            $pi_count++;
                            $joins['info_' . $info_key] = " LEFT JOIN {postinfo} ipi{$pi_count} ON {posts}.id = ipi{$pi_count}.post_id AND ipi{$pi_count}.name = ? AND ipi{$pi_count}.value = ?";
                            $join_params[] = $info_key;
                            $join_params[] = $info_value;
                            $where[] = "ipi{$pi_count}.name <> ''";
                            $select_ary["info_{$info_key}_value"] = "ipi{$pi_count}.value AS info_{$info_key}_value";
                        }
                    }
                }
                if (isset($paramset['any:info'])) {
                    if (Utils::is_traversable($paramset['any:info'])) {
                        $pi_count = 0;
                        $pi_where = array();
                        foreach ($paramset['any:info'] as $info_key => $info_value) {
                            $pi_count++;
                            $join_params[] = $info_key;
                            if (is_array($info_value)) {
                                $joins['any_info_' . $info_key] = " LEFT JOIN {postinfo} aipi{$pi_count} ON {posts}.id = aipi{$pi_count}.post_id AND aipi{$pi_count}.name = ? AND aipi{$pi_count}.value IN (" . Utils::placeholder_string(count($info_value)) . ")";
                                $join_params = array_merge($join_params, $info_value);
                            } else {
                                $joins['any_info_' . $info_key] = " LEFT JOIN {postinfo} aipi{$pi_count} ON {posts}.id = aipi{$pi_count}.post_id AND aipi{$pi_count}.name = ? AND aipi{$pi_count}.value = ?";
                                $join_params[] = $info_value;
                            }
                            $pi_where[] = "aipi{$pi_count}.name <> ''";
                            $select_ary["info_{$info_key}_value"] = "aipi{$pi_count}.value AS info_{$info_key}_value";
                        }
                        $where[] = '(' . implode(' OR ', $pi_where) . ')';
                    }
                }
                if (isset($paramset['has:info'])) {
                    $the_ins = array();
                    $has_info = Utils::single_array($paramset['has:info']);
                    $pi_count = 0;
                    $pi_where = array();
                    foreach ($has_info as $info_name) {
                        $pi_count++;
                        $joins['has_info_' . $info_name] = " LEFT JOIN {postinfo} hipi{$pi_count} ON {posts}.id = hipi{$pi_count}.post_id AND hipi{$pi_count}.name = ?";
                        $join_params[] = $info_name;
                        $pi_where[] = "hipi{$pi_count}.name <> ''";
                        $select_ary["info_{$info_name}_value"] = "hipi{$pi_count}.value AS info_{$info_name}_value";
                    }
                    $where[] = '(' . implode(' OR ', $pi_where) . ')';
                }
                if (isset($paramset['not:all:info']) || isset($paramset['not:info'])) {
                    // merge the two possible calls together
                    $infos = array_merge(isset($paramset['not:all:info']) ? $paramset['not:all:info'] : array(), isset($paramset['not:info']) ? $paramset['not:info'] : array());
                    if (Utils::is_traversable($infos)) {
                        $the_ins = array();
                        foreach ($infos as $info_key => $info_value) {
                            $the_ins[] = ' ({postinfo}.name = ? AND {postinfo}.value = ? ) ';
                            $params[] = $info_key;
                            $params[] = $info_value;
                        }
                        $where[] = '
							{posts}.id NOT IN (
							SELECT post_id FROM {postinfo}
							WHERE ( ' . implode(' OR ', $the_ins) . ' )
							GROUP BY post_id
							HAVING COUNT(*) = ' . count($infos) . ' )
						';
                        // see that hard-coded number? sqlite wets itself if we use a bound parameter... don't change that
                    }
                }
                if (isset($paramset['not:any:info'])) {
                    if (Utils::is_traversable($paramset['not:any:info'])) {
                        foreach ($paramset['not:any:info'] as $info_key => $info_value) {
                            $the_ins[] = ' ({postinfo}.name = ? AND {postinfo}.value = ? ) ';
                            $params[] = $info_key;
                            $params[] = $info_value;
                        }
                        $where[] = '
							{posts}.id NOT IN (
								SELECT post_id FROM {postinfo}
								WHERE ( ' . implode(' OR ', $the_ins) . ' )
							)
						';
                    }
                }
                /**
                 * Build the statement needed to filter by pubdate:
                 * If we've got the day, then get the date;
                 * If we've got the month, but no date, get the month;
                 * If we've only got the year, get the whole year.
                 */
                if (isset($paramset['day']) && isset($paramset['month']) && isset($paramset['year'])) {
                    $where[] = 'pubdate BETWEEN ? AND ?';
                    $startDate = sprintf('%d-%02d-%02d', $paramset['year'], $paramset['month'], $paramset['day']);
                    $startDate = HabariDateTime::date_create($startDate);
                    $params[] = $startDate->sql;
                    $params[] = $startDate->modify('+1 day')->sql;
                    //$params[] = date( 'Y-m-d H:i:s', mktime( 0, 0, 0, $paramset['month'], $paramset['day'], $paramset['year'] ) );
                    //$params[] = date( 'Y-m-d H:i:s', mktime( 23, 59, 59, $paramset['month'], $paramset['day'], $paramset['year'] ) );
                } elseif (isset($paramset['month']) && isset($paramset['year'])) {
                    $where[] = 'pubdate BETWEEN ? AND ?';
                    $startDate = sprintf('%d-%02d-%02d', $paramset['year'], $paramset['month'], 1);
                    $startDate = HabariDateTime::date_create($startDate);
                    $params[] = $startDate->sql;
                    $params[] = $startDate->modify('+1 month')->sql;
                    //$params[] = date( 'Y-m-d H:i:s', mktime( 0, 0, 0, $paramset['month'], 1, $paramset['year'] ) );
                    //$params[] = date( 'Y-m-d H:i:s', mktime( 23, 59, 59, $paramset['month'] + 1, 0, $paramset['year'] ) );
                } elseif (isset($paramset['year'])) {
                    $where[] = 'pubdate BETWEEN ? AND ?';
                    $startDate = sprintf('%d-%02d-%02d', $paramset['year'], 1, 1);
                    $startDate = HabariDateTime::date_create($startDate);
                    $params[] = $startDate->sql;
                    $params[] = $startDate->modify('+1 year')->sql;
                    //$params[] = date( 'Y-m-d H:i:s', mktime( 0, 0, 0, 1, 1, $paramset['year'] ) );
                    //$params[] = date( 'Y-m-d H:i:s', mktime( 0, 0, -1, 1, 1, $paramset['year'] + 1 ) );
                }
                if (isset($paramset['after'])) {
                    $where[] = 'pubdate > ?';
                    $params[] = HabariDateTime::date_create($paramset['after'])->sql;
                }
                if (isset($paramset['before'])) {
                    $where[] = 'pubdate < ?';
                    $params[] = HabariDateTime::date_create($paramset['before'])->sql;
                }
                // Concatenate the WHERE clauses
                if (count($where) > 0) {
                    $wheres[] = ' (' . implode(' AND ', $where) . ') ';
                }
            }
        }
        // Only show posts to which the current user has permission
        if (isset($paramset['ignore_permissions'])) {
            $master_perm_where = '';
        } else {
            // This set of wheres will be used to generate a list of post_ids that this user can read
            $perm_where = array();
            $perm_where_denied = array();
            $params_where = array();
            $where = array();
            // Get the tokens that this user is granted or denied access to read
            $read_tokens = isset($paramset['read_tokens']) ? $paramset['read_tokens'] : ACL::user_tokens(User::identify(), 'read', true);
            $deny_tokens = isset($paramset['deny_tokens']) ? $paramset['deny_tokens'] : ACL::user_tokens(User::identify(), 'deny', true);
            // If a user can read his own posts, let him
            if (User::identify()->can('own_posts', 'read')) {
                $perm_where['own_posts_id'] = '{posts}.user_id = ?';
                $params_where[] = User::identify()->id;
            }
            // If a user can read any post type, let him
            if (User::identify()->can('post_any', 'read')) {
                $perm_where = array('post_any' => '(1=1)');
                $params_where = array();
            } else {
                // If a user can read specific post types, let him
                $permitted_post_types = array();
                foreach (Post::list_active_post_types() as $name => $posttype) {
                    if (User::identify()->can('post_' . Utils::slugify($name), 'read')) {
                        $permitted_post_types[] = $posttype;
                    }
                }
                if (count($permitted_post_types) > 0) {
                    $perm_where[] = '{posts}.content_type IN (' . implode(',', $permitted_post_types) . ')';
                }
                // If a user can read posts with specific tokens, let him
                if (count($read_tokens) > 0) {
                    $joins['post_tokens__allowed'] = ' LEFT JOIN {post_tokens} pt_allowed ON {posts}.id= pt_allowed.post_id AND pt_allowed.token_id IN (' . implode(',', $read_tokens) . ')';
                    $perm_where['perms_join_null'] = 'pt_allowed.post_id IS NOT NULL';
                }
            }
            // If a user is denied access to all posts, do so
            if (User::identify()->cannot('post_any')) {
                $perm_where_denied = array('(1=0)');
            } else {
                // If a user is denied read access to specific post types, deny him
                $denied_post_types = array();
                foreach (Post::list_active_post_types() as $name => $posttype) {
                    if (User::identify()->cannot('post_' . Utils::slugify($name))) {
                        $denied_post_types[] = $posttype;
                    }
                }
                if (count($denied_post_types) > 0) {
                    $perm_where_denied[] = '{posts}.content_type NOT IN (' . implode(',', $denied_post_types) . ')';
                }
            }
            // If there are granted permissions to check, add them to the where clause
            if (count($perm_where) == 0 && !isset($joins['post_tokens__allowed'])) {
                // You have no grants.  You get no posts.
                $where['perms_granted'] = '(1=0)';
            } elseif (count($perm_where) > 0) {
                $where['perms_granted'] = '
					(' . implode(' OR ', $perm_where) . ')
				';
                $params = array_merge($join_params, $params, $params_where);
            }
            if (count($deny_tokens) > 0) {
                $joins['post_tokens__denied'] = ' LEFT JOIN {post_tokens} pt_denied ON {posts}.id= pt_denied.post_id AND pt_denied.token_id IN (' . implode(',', $deny_tokens) . ')';
                $perm_where_denied['perms_join_null'] = 'pt_denied.post_id IS NULL';
            }
            // If there are denied permissions to check, add them to the where clause
            if (count($perm_where_denied) > 0) {
                $where['perms_denied'] = '
					(' . implode(' AND ', $perm_where_denied) . ')
				';
            }
            $master_perm_where = implode(' AND ', $where);
        }
        // Extract the remaining parameters which will be used onwards
        // For example: page number, fetch function, limit
        $paramarray = new SuperGlobal($paramarray);
        $extract = $paramarray->filter_keys('page', 'fetch_fn', 'count', 'orderby', 'groupby', 'limit', 'offset', 'nolimit', 'having');
        foreach ($extract as $key => $value) {
            ${$key} = $value;
        }
        // Define the LIMIT if it does not exist, unless specific posts are requested
        if (!isset($limit) && !isset($paramset['id']) && !isset($paramset['slug'])) {
            $limit = Options::get('pagination') ? (int) Options::get('pagination') : 5;
        } elseif (!isset($limit)) {
            $selected_posts = 0;
            if (isset($paramset['id'])) {
                $selected_posts += count(Utils::single_array($paramset['id']));
            }
            if (isset($paramset['slug'])) {
                $selected_posts += count(Utils::single_array($paramset['slug']));
            }
            $limit = $selected_posts > 0 ? $selected_posts : '';
        }
        // Calculate the OFFSET based on the page number
        if (isset($page) && is_numeric($page) && !isset($paramset['offset'])) {
            $offset = (intval($page) - 1) * intval($limit);
        }
        /**
         * Determine which fetch function to use:
         * If it is specified, make sure it is valid (based on the $fns array defined at the beginning of this function);
         * Else, use 'get_results' which will return a Posts array of Post objects.
         */
        if (isset($fetch_fn)) {
            if (!in_array($fetch_fn, $fns)) {
                $fetch_fn = $fns[0];
            }
        } else {
            $fetch_fn = $fns[0];
        }
        /**
         * Turn the requested fields into a comma-separated SELECT field clause
         */
        $select = implode(', ', $select_ary);
        /**
         * If a count is requested:
         * Replace the current fields to select with a COUNT();
         * Change the fetch function to 'get_value';
         * Remove the ORDER BY since it's useless.
         * Remove the GROUP BY (tag search added it)
         */
        if (isset($count)) {
            $select = "COUNT({$count})";
            $fetch_fn = 'get_value';
            $orderby = '';
            $groupby = '';
            $having = '';
        }
        // If the month counts are requested, replaced the select clause
        if (isset($paramset['month_cts'])) {
            if (isset($paramset['tag']) || isset($paramset['tag_slug'])) {
                $select = 'MONTH(FROM_UNIXTIME(pubdate)) AS month, YEAR(FROM_UNIXTIME(pubdate)) AS year, COUNT(DISTINCT {posts}.id) AS ct';
            } else {
                $select = 'MONTH(FROM_UNIXTIME(pubdate)) AS month, YEAR(FROM_UNIXTIME(pubdate)) AS year, COUNT(*) AS ct';
            }
            $groupby = 'year, month';
            $orderby = 'year, month';
        }
        // Remove the LIMIT if 'nolimit' or 'month_cts' is set
        // Doing this first should allow OFFSET to work
        if (isset($nolimit) || isset($paramset['month_cts'])) {
            $limit = '';
        }
        // Define the LIMIT and add the OFFSET if it exists
        if (!empty($limit)) {
            $limit = " LIMIT {$limit}";
            if (isset($offset)) {
                $limit .= " OFFSET {$offset}";
            }
        } else {
            $limit = '';
        }
        /* All SQL parts are constructed, on to real business! */
        /**
         * Build the final SQL statement
         */
        $query = '
			SELECT DISTINCT ' . $select . '
			FROM {posts} ' . implode(' ', $joins);
        if (count($wheres) > 0) {
            $query .= ' WHERE (' . implode(" \nOR\n ", $wheres) . ')';
            $query .= $master_perm_where == '' ? '' : ' AND (' . $master_perm_where . ')';
        } elseif ($master_perm_where != '') {
            $query .= ' WHERE (' . $master_perm_where . ')';
        }
        $query .= !isset($groupby) || $groupby == '' ? '' : ' GROUP BY ' . $groupby;
        $query .= !isset($having) || $having == '' ? '' : ' HAVING ' . $having;
        $query .= ($orderby == '' ? '' : ' ORDER BY ' . $orderby) . $limit;
        /**
         * DEBUG: Uncomment the following line to display everything that happens in this function
         */
        //print_R('<pre>'.$query.'</pre>');
        //Utils::debug( $paramarray, $fetch_fn, $query, $params );
        //Session::notice($query);
        /**
         * Execute the SQL statement using the PDO extension
         */
        DB::set_fetch_mode(PDO::FETCH_CLASS);
        DB::set_fetch_class('Post');
        $results = DB::$fetch_fn($query, $params, 'Post');
        //		Utils::debug( $paramarray, $fetch_fn, $query, $params, $results );
        //		var_dump( $query );
        /**
         * Return the results
         */
        if ('get_results' != $fetch_fn) {
            // Since a single result was requested, return a single Post object.
            return $results;
        } elseif (is_array($results)) {
            // With multiple results, return a Posts array of Post objects.
            $c = __CLASS__;
            $return_value = new $c($results);
            $return_value->get_param_cache = $paramarray;
            return $return_value;
        }
    }
 /**
  * Method called to associate a Vocabulary object to this object
  * through the Vocabulary foreign key attribute
  *
  * @param      Vocabulary $l Vocabulary
  * @return     void
  * @throws     PropelException
  */
 public function addVocabulary(Vocabulary $l)
 {
     $this->collVocabularys[] = $l;
     $l->setAgent($this);
 }