/bedita-app/models/category.php
PHP | 507 lines | 331 code | 64 blank | 112 comment | 48 complexity | 274b037a1b1249ed3a83a1355a0116fb MD5 | raw file
Possible License(s): AGPL-1.0, AGPL-3.0, LGPL-3.0, LGPL-2.1, GPL-3.0
- <?php
- /*-----8<--------------------------------------------------------------------
- *
- * BEdita - a semantic content management framework
- *
- * Copyright 2008 ChannelWeb Srl, Chialab Srl
- *
- * This file is part of BEdita: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- * BEdita is distributed WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public License
- * version 3 along with BEdita (see LICENSE.LGPL).
- * If not, see <http://gnu.org/licenses/lgpl-3.0.html>.
- *
- *------------------------------------------------------------------->8-----
- */
- /**
- * Generic category
- *
- * @version $Revision: 3905 $
- * @modifiedby $LastChangedBy: ste $
- * @lastmodified $LastChangedDate: 2012-08-08 18:21:17 +0200 (Wed, 08 Aug 2012) $
- *
- * $Id: category.php 3905 2012-08-08 16:21:17Z ste $
- */
- class Category extends BEAppModel {
- var $actsAs = array(
- 'CompactResult' => array()
- );
-
- var $validate = array(
- 'label' => array(
- 'rule' => 'notEmpty'
- ),
- 'status' => array(
- 'rule' => 'notEmpty'
- ),
- 'name' => array(
- 'rule' => 'notEmpty'
- )
- ) ;
- // static vars used by reorderTag static function
- static $dirTag, $orderTag;
-
- function afterFind($result) {
- foreach ($result as &$res) {
- if(isset($res['name']))
- $res['url_label'] = $res['name'];
- }
- return $result;
- }
- public function tagLabelPresent($label, $exclude_id=null) {
- $tagDB = $this->find("first",
- array("conditions" => "object_type_id IS NULL AND name='".addslashes($label)."' " . $this->collateStatment() ) );
-
- if (!empty($exclude_id) && $exclude_id == $tagDB["id"])
- return false;
-
- return !empty($tagDB);
- }
- /**
- * Get tag label from unique name
- *
- * @param string $name
- */
- public function tagLabelFromName($name) {
- $tagDB = $this->find("first",
- array("conditions" => "object_type_id IS NULL AND name='$name'"));
- return !empty($tagDB) ? $tagDB['label'] : "";
- }
-
-
- /**
- * Define a unique name from label: lowercase, trimmed, etc...
- *
- * @param string $label
- */
- public function uniqueLabelName($label) {
- $baseName = $name = BeLib::getInstance()->friendlyUrlString($label);
- // search for already used label
-
- // suffix counter
- $i = 1;
-
- // if it's a category
- if (!empty($this->data[$this->alias]["object_type_id"])) {
- // if name is in mediaTypes
- if (in_array($name, Configure::read("mediaTypes"))) {
- // if multimedia object return baseName
- if (in_array($this->data[$this->alias]["object_type_id"], Configure::read("objectTypes.multimedia.id"))) {
- return $baseName;
- } else {
- $name = $baseName . "-" . $i++;
- }
- }
- $conditions["NOT"] = array("object_type_id" => $this->data[$this->alias]["object_type_id"]);
- $conditions[] = "object_type_id IS NOT NULL";
-
- // if it's a tag
- } else {
- $conditions[] = "object_type_id IS NULL";
- }
- $conditions["name"] = $name;
- // exclude itself if already present
- if (!empty($this->data[$this->alias]["id"])) {
- $conditions["NOT"]["id"] = $this->data[$this->alias]["id"];
- }
- $count = $this->find("count", array("conditions" => $conditions));
-
- if ($count > 0) {
- $freeName = false;
- while (!$freeName) {
- $conditions["name"] = $baseName . "-" . $i++;
- $count = $this->find("count", array("conditions" => $conditions));
- if ($count == 0) {
- $freeName = true;
- $name = $conditions["name"];
- }
- }
- }
- return $name;
- }
-
- /**
- * Define default values
- */
- function beforeValidate() {
- $data = &$this->data[$this->name] ;
- $data['name'] = $this->uniqueLabelName($data["label"]);
- return true;
- }
-
- /**
- * Get all categories of some object type and order them by area
- *
- * @param int $objectType
- * @return array(
- * "area" => array(
- * nomearea => array(categories in that area)),
- * "noarea" => array(categories aren't in any area)
- * )
- */
- public function getCategoriesByArea($objectType) {
-
- $categories = $this->find("all", array(
- "conditions" => array("Category.object_type_id" => $objectType), "order" => "label"
- ));
-
- $objModel = ClassRegistry::init("BEObject");
- $areaList = $objModel->find('list', array(
- "conditions" => "object_type_id=" . Configure::read("objectTypes.area.id"),
- "order" => "title",
- "fields" => "BEObject.title"
- )
- );
-
- $areaCategory = array();
-
- foreach ($categories as $cat) {
- if (array_key_exists($cat["area_id"],$areaList)) {
- $areaCategory["area"][$areaList[$cat["area_id"]]][] = $cat;
- } else {
- $areaCategory["noarea"][] = $cat;
- }
- }
-
- return $areaCategory;
- }
-
-
- private function collateStatment() {
- $res = "";
- // #MYSQL
- if($this->getDriver() == "mysql") {
- $res = "collate utf8_bin";
- }
- return $res;
- }
-
- /**
- * save a list of comma separated tag
- *
- * @param comma separated string $tagList
- * @return array of tags' id
- */
- public function saveTagList($tagList) {
- $arrIdTag = array();
- if (!empty($tagList)) {
- $tags = explode(",", $tagList);
-
- foreach ($tags as $tag) {
- $tag = trim($tag);
-
- if (!empty($tag)) {
-
- $tagDB = $this->find("first", array(
- "conditions" => "object_type_id IS NULL AND label='".addslashes($tag)."' " .
- $this->collateStatment()
- )
- );
- if (empty($tagDB)) {
- $tagDB["label"] = $tag;
- $tagDB["status"] = "on";
- $this->create();
- if (!$this->save($tagDB)) {
- throw new BeditaException(__("Error saving tags", true));
- }
- }
- $id_tag = (!empty($tagDB["id"]))? $tagDB["id"] : $this->getLastInsertID();
- if (!in_array($id_tag,$arrIdTag)) {
- $arrIdTag[$id_tag] = $id_tag;
- }
- }
- }
- }
- return $arrIdTag;
- }
-
- /**
- * return list of tags with their weight
- *
- * @param array $options
- * "showOrphans" => true, show all tags also not associated
- * "status" => null, string or array (on, off, draft). if area_id is setted "status" is used also to related objects
- * "cloud" => false, true to set a css class for cloud view
- * "coeff" => 12, coeffiecient for calculate the distribution
- * "order" => "label", order by field
- * "dir" => 1, asc(1), desc(0)
- * "area_id"=> null get tags only associated to objects that are in "area_id" publication
- *
- * @return array
- */
- public function getTags(array $options = array()) {
- $options = array_merge(
- array("showOrphans" => true, "status" => null, "cloud" => false,
- "coeff" => 12, "order" => "label", "dir" => 1, "area_id"=> null, "section_id" => null),
- (array)$options
- );
-
- $conditions = array();
- $conditions[] = "Category.object_type_id IS NULL";
- if(!empty($options["status"])) {
- $conditions["Category.status"] = $options["status"];
- }
-
- $orderSql = ($options["order"] != "weight")? $options["order"] : "label";
- $dirSql = ($options["dir"])? "ASC" : "DESC";
- $joinsBEObject = array();
- $joins = array();
- // get tags associated to objects that are in $area_id publication or $section_id section
- if (!empty($options["area_id"]) || !empty($options["section_id"])) {
- $joinsBEObject = array(
- 'table' => 'objects',
- 'alias' => 'BEObject',
- 'type' => 'inner',
- 'conditions'=> array(
- 'BEObject.id = ObjectCategory.object_id'
- )
- );
- if (!empty($options["status"])) {
- $joinsBEObject["conditions"]['BEObject.status'] = $options["status"];
- }
- $treeCondition = array('Tree.id = BEObject.id');
- if(!empty($options["section_id"])) {
- $treeCondition['Tree.parent_id'] = $options["section_id"];
- } else {
- $treeCondition['Tree.area_id'] = $options["area_id"];
- }
-
- $joinsTree = array(
- 'table' => 'trees',
- 'alias' => 'Tree',
- 'type' => 'inner',
- 'conditions'=> $treeCondition
- );
- $joins = array(
- array(
- 'table' => 'object_categories',
- 'alias' => 'ObjectCategory',
- 'type' => 'inner',
- 'conditions'=> array('ObjectCategory.category_id = Category.id')
- ),
- $joinsBEObject,
- $joinsTree
- );
- }
- $allTags = $this->find('all', array(
- 'conditions'=> $conditions,
- 'order' => array("Category." . $orderSql => $dirSql),
- 'group' => $this->fieldsString("Category"),
- 'joins' => $joins
- ));
-
- $tags = array();
- foreach ($allTags as $t) {
- $tags[$t['id']] = $t;
- }
- $category_ids = Set::extract('/id', $allTags);
-
- $objCatModel = ClassRegistry::init("ObjectCategory");
- $joins = (empty($joinsBEObject))? array() : array($joinsBEObject, $joinsTree);
- $res = $objCatModel->find("all", array(
- 'fields' => array("DISTINCT ObjectCategory.category_id", "ObjectCategory.object_id"),
- 'conditions' => array("ObjectCategory.category_id" => $category_ids),
- 'joins' => $joins
- ));
-
- // calculate weights
- $weights = array(0);
- foreach ($res as $val) {
- if (empty($weights[$val["ObjectCategory"]["category_id"]])) {
- $weights[$val["ObjectCategory"]["category_id"]] = 1;
- } else {
- $weights[$val["ObjectCategory"]["category_id"]]++;
- }
- }
-
- if ($options["cloud"]) {
- $max = max($weights);
- $min = min($weights);
- $distribution = ($max - $min) / $options["coeff"];
- }
-
- foreach ($res as $r) {
- $key = !empty($r['ObjectCategory']['category_id']) ? $r['ObjectCategory']['category_id'] : $r[0]['category_id'] ;
- $w = $weights[$r["ObjectCategory"]["category_id"]];
- $tags[$key]['weight'] = $w;
- if ($options["cloud"]) {
- if ($w == $min)
- $tags[$key]['class'] = "smallestTag";
- elseif ($w == $max)
- $tags[$key]['class'] = "largestTag";
- elseif ($w > ($min + ($distribution * 2)))
- $tags[$key]['class'] = "largeTag";
- elseif ($w > ($min + $distribution))
- $tags[$key]['class'] = "mediumTag";
- else
- $tags[$key]['class'] = "smallTag";
- }
- }
-
- // remove orphans or set weight = 0, create the non-associative array
- $tagsArray = array();
- foreach ($tags as $k => $t) {
- $tags[$k]['url_label'] = $t['name'];
- if(!isset($t['weight'])) {
- if($options["showOrphans"] === false) {
- unset($tags[$k]);
- } else {
- $tags[$k]['weight'] = 0;
- $tagsArray[]= $tags[$k];
- }
- } else {
- $tagsArray[]= $tags[$k];
- }
- }
-
- // if order by weight reorder tags
- if ($options["order"] == "weight") {
- Category::$orderTag = $options["order"];
- Category::$dirTag = $options["dir"];
- usort($tagsArray, array('Category', 'reorderTag'));
- }
- // pr($tagsArray);exit;
- return $tagsArray;
- }
-
-
- public function getContentsByTag($name) {
- // bind association on the fly
- $hasAndBelongsToMany = array(
- 'BEObject' =>
- array(
- 'className' => 'BEObject',
- 'joinTable' => 'object_categories',
- 'foreignKey' => 'category_id',
- 'associationForeignKey' => 'object_id',
- 'unique' => true
- )
- );
-
- $this->bindModel( array(
- 'hasAndBelongsToMany' => $hasAndBelongsToMany
- )
- );
-
- // don't compact find result
- $this->bviorCompactResults = false;
- $tag = $this->find("first", array(
- "conditions" => "object_type_id IS NULL AND name='".addslashes($name)."' ".
- $this->collateStatment(),
- "contain" => array("BEObject" => array("ObjectType"))
- )
- );
-
- // reset to default compact result
- $this->bviorCompactResults = true;
-
- return empty($tag["BEObject"]) ? array() : $tag["BEObject"];
- }
- /**
- * USED for multimedia objects
- * check if exists $mediatype in categories for an object type. If not, create the category
- *
- * @param int $object_type_id
- * @return mixed, false if not mediatype in the form else return array of Category
- */
- public function checkMediaType($object_type_id, $mediatype) {
-
- if (empty($mediatype)) {
- return false;
- }
-
- $category = $this->find("first",
- array(
- "conditions" => array(
- "name" => $mediatype,
- "object_type_id" => $object_type_id
- )
- )
- );
- if(empty($category)) { // if media category doesn't exists, create it
- $data = array(
- "name"=>$mediatype,
- "label"=>ucfirst($mediatype),
- "object_type_id"=>$object_type_id,
- "status"=>"on"
- );
- $this->create();
- if(!$this->save($data)) {
- throw new BeditaException(__("Error saving category", true), $this->validationErrors);
- }
- $category['id']=$this->id;
- }
- $categoryArr = array($category['id']=>$category['id']);
- return $categoryArr;
- }
-
- /**
- * compare two array elements defined by $orderTag var and return -1,0,1
- * $dirTag is used for define order of comparison
- *
- * @param array $e1
- * @param array $e2
- * @return int (-1,0,1)
- */
- private static function reorderTag($e1, $e2) {
- $d1 = $e1[Category::$orderTag];
- $d2 = $e2[Category::$orderTag];
- return (Category::$dirTag)? strcmp($d1,$d2) : strcmp($d2,$d1);
- }
-
-
- /**
- * Search for category names, create if not already present, and
- * return array of corresponding id
- *
- * @param array $names, category names to search/create
- * @param int $objTypeId, category object type id
- * @return array of corresponding id-category
- */
- public function findCreateCategories(array &$names, $objTypeId) {
- $res = array();
- // if not exists create
- foreach ($names as $n) {
- $this->create();
- $n = trim($n);
- $this->bviorCompactResults = false;
- $idCat = $this->field('id', array('name' => $n, 'object_type_id' => $objTypeId));
- $this->bviorCompactResults = true;
- if(empty($idCat)) {
- $dataCat = array('name'=> $n,'label' => $n,
- 'object_type_id' => $objTypeId, 'status'=>'on');
- if(!$this->save($dataCat)) {
- throw new BeditaException(__("Error saving category") . ": " . print_r($dataCat, true));
- }
- $idCat = $this->id;
- }
- $res[] = $idCat;
- }
- return $res;
- }
- }
- ?>