Merge pull request #4892 from owncloud/vcategories_public
OC_VCategories => OC\Tags. Public interface and getter in server containerremotes/origin/stable6
commit
469b309b21
@ -0,0 +1,48 @@ |
||||
<?php |
||||
/** |
||||
* ownCloud |
||||
* |
||||
* @author Thomas Tanghus |
||||
* @copyright 2013 Thomas Tanghus <thomas@tanghus.net> |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
/** |
||||
* Factory class creating instances of \OCP\ITags |
||||
* |
||||
* A tag can be e.g. 'Family', 'Work', 'Chore', 'Special Occation' or |
||||
* anything else that is either parsed from a vobject or that the user chooses |
||||
* to add. |
||||
* Tag names are not case-sensitive, but will be saved with the case they |
||||
* are entered in. If a user already has a tag 'family' for a type, and |
||||
* tries to add a tag named 'Family' it will be silently ignored. |
||||
*/ |
||||
|
||||
namespace OCP; |
||||
|
||||
interface ITagManager { |
||||
|
||||
/** |
||||
* Create a new \OCP\ITags instance and load tags from db. |
||||
* |
||||
* @see \OCP\ITags |
||||
* @param string $type The type identifier e.g. 'contact' or 'event'. |
||||
* @param array $defaultTags An array of default tags to be used if none are stored. |
||||
* @return \OCP\ITags |
||||
*/ |
||||
public function load($type, $defaultTags=array()); |
||||
|
||||
} |
@ -0,0 +1,164 @@ |
||||
<?php |
||||
/** |
||||
* ownCloud |
||||
* |
||||
* @author Thomas Tanghus |
||||
* @copyright 2013 Thomas Tanghus <thomas@tanghus.net> |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
namespace OCP; |
||||
|
||||
// FIXME: Where should I put this? Or should it be implemented as a Listener? |
||||
\OC_Hook::connect('OC_User', 'post_deleteUser', 'OC\Tags', 'post_deleteUser'); |
||||
|
||||
/** |
||||
* Class for easily tagging objects by their id |
||||
* |
||||
* A tag can be e.g. 'Family', 'Work', 'Chore', 'Special Occation' or |
||||
* anything else that is either parsed from a vobject or that the user chooses |
||||
* to add. |
||||
* Tag names are not case-sensitive, but will be saved with the case they |
||||
* are entered in. If a user already has a tag 'family' for a type, and |
||||
* tries to add a tag named 'Family' it will be silently ignored. |
||||
*/ |
||||
|
||||
interface ITags { |
||||
|
||||
/** |
||||
* Check if any tags are saved for this type and user. |
||||
* |
||||
* @return boolean. |
||||
*/ |
||||
public function isEmpty(); |
||||
|
||||
/** |
||||
* Get the tags for a specific user. |
||||
* |
||||
* This returns an array with id/name maps: |
||||
* [ |
||||
* ['id' => 0, 'name' = 'First tag'], |
||||
* ['id' => 1, 'name' = 'Second tag'], |
||||
* ] |
||||
* |
||||
* @returns array |
||||
*/ |
||||
public function getTags(); |
||||
|
||||
/** |
||||
* Get the a list if items tagged with $tag. |
||||
* |
||||
* Throws an exception if the tag could not be found. |
||||
* |
||||
* @param string|integer $tag Tag id or name. |
||||
* @return array An array of object ids or false on error. |
||||
*/ |
||||
public function getIdsForTag($tag); |
||||
|
||||
/** |
||||
* Checks whether a tag is already saved. |
||||
* |
||||
* @param string $name The name to check for. |
||||
* @return bool |
||||
*/ |
||||
public function hasTag($name); |
||||
|
||||
/** |
||||
* Add a new tag. |
||||
* |
||||
* @param string $name A string with a name of the tag |
||||
* @return int the id of the added tag or false if it already exists. |
||||
*/ |
||||
public function add($name); |
||||
|
||||
/** |
||||
* Rename tag. |
||||
* |
||||
* @param string $from The name of the existing tag |
||||
* @param string $to The new name of the tag. |
||||
* @return bool |
||||
*/ |
||||
public function rename($from, $to); |
||||
|
||||
/** |
||||
* Add a list of new tags. |
||||
* |
||||
* @param string[] $names A string with a name or an array of strings containing |
||||
* the name(s) of the to add. |
||||
* @param bool $sync When true, save the tags |
||||
* @param int|null $id int Optional object id to add to this|these tag(s) |
||||
* @return bool Returns false on error. |
||||
*/ |
||||
public function addMultiple($names, $sync=false, $id = null); |
||||
|
||||
/** |
||||
* Delete tag/object relations from the db |
||||
* |
||||
* @param array $ids The ids of the objects |
||||
* @return boolean Returns false on error. |
||||
*/ |
||||
public function purgeObjects(array $ids); |
||||
|
||||
/** |
||||
* Get favorites for an object type |
||||
* |
||||
* @return array An array of object ids. |
||||
*/ |
||||
public function getFavorites(); |
||||
|
||||
/** |
||||
* Add an object to favorites |
||||
* |
||||
* @param int $objid The id of the object |
||||
* @return boolean |
||||
*/ |
||||
public function addToFavorites($objid); |
||||
|
||||
/** |
||||
* Remove an object from favorites |
||||
* |
||||
* @param int $objid The id of the object |
||||
* @return boolean |
||||
*/ |
||||
public function removeFromFavorites($objid); |
||||
|
||||
/** |
||||
* Creates a tag/object relation. |
||||
* |
||||
* @param int $objid The id of the object |
||||
* @param int|string $tag The id or name of the tag |
||||
* @return boolean Returns false on database error. |
||||
*/ |
||||
public function tagAs($objid, $tag); |
||||
|
||||
/** |
||||
* Delete single tag/object relation from the db |
||||
* |
||||
* @param int $objid The id of the object |
||||
* @param int|string $tag The id or name of the tag |
||||
* @return boolean |
||||
*/ |
||||
public function unTag($objid, $tag); |
||||
|
||||
/** |
||||
* Delete tags from the |
||||
* |
||||
* @param string[] $names An array of tags to delete |
||||
* @return bool Returns false on error |
||||
*/ |
||||
public function delete($names); |
||||
|
||||
} |
@ -0,0 +1,68 @@ |
||||
<?php |
||||
/** |
||||
* ownCloud |
||||
* |
||||
* @author Thomas Tanghus |
||||
* @copyright 2013 Thomas Tanghus <thomas@tanghus.net> |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
/** |
||||
* Factory class creating instances of \OCP\ITags |
||||
* |
||||
* A tag can be e.g. 'Family', 'Work', 'Chore', 'Special Occation' or |
||||
* anything else that is either parsed from a vobject or that the user chooses |
||||
* to add. |
||||
* Tag names are not case-sensitive, but will be saved with the case they |
||||
* are entered in. If a user already has a tag 'family' for a type, and |
||||
* tries to add a tag named 'Family' it will be silently ignored. |
||||
*/ |
||||
|
||||
namespace OC; |
||||
|
||||
class TagManager implements \OCP\ITagManager { |
||||
|
||||
/** |
||||
* User |
||||
* |
||||
* @var string |
||||
*/ |
||||
private $user = null; |
||||
|
||||
/** |
||||
* Constructor. |
||||
* |
||||
* @param string $user The user whos data the object will operate on. |
||||
*/ |
||||
public function __construct($user) { |
||||
|
||||
$this->user = $user; |
||||
|
||||
} |
||||
|
||||
/** |
||||
* Create a new \OCP\ITags instance and load tags from db. |
||||
* |
||||
* @see \OCP\ITags |
||||
* @param string $type The type identifier e.g. 'contact' or 'event'. |
||||
* @param array $defaultTags An array of default tags to be used if none are stored. |
||||
* @return \OCP\ITags |
||||
*/ |
||||
public function load($type, $defaultTags=array()) { |
||||
return new Tags($this->user, $type, $defaultTags); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,642 @@ |
||||
<?php |
||||
/** |
||||
* ownCloud |
||||
* |
||||
* @author Thomas Tanghus |
||||
* @copyright 2012-2013 Thomas Tanghus <thomas@tanghus.net> |
||||
* @copyright 2012 Bart Visscher bartv@thisnet.nl |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
/** |
||||
* Class for easily tagging objects by their id |
||||
* |
||||
* A tag can be e.g. 'Family', 'Work', 'Chore', 'Special Occation' or |
||||
* anything else that is either parsed from a vobject or that the user chooses |
||||
* to add. |
||||
* Tag names are not case-sensitive, but will be saved with the case they |
||||
* are entered in. If a user already has a tag 'family' for a type, and |
||||
* tries to add a tag named 'Family' it will be silently ignored. |
||||
*/ |
||||
|
||||
namespace OC; |
||||
|
||||
class Tags implements \OCP\ITags { |
||||
|
||||
/** |
||||
* Tags |
||||
* |
||||
* @var array |
||||
*/ |
||||
private $tags = array(); |
||||
|
||||
/** |
||||
* Used for storing objectid/categoryname pairs while rescanning. |
||||
* |
||||
* @var array |
||||
*/ |
||||
private static $relations = array(); |
||||
|
||||
/** |
||||
* Type |
||||
* |
||||
* @var string |
||||
*/ |
||||
private $type = null; |
||||
|
||||
/** |
||||
* User |
||||
* |
||||
* @var string |
||||
*/ |
||||
private $user = null; |
||||
|
||||
const TAG_TABLE = '*PREFIX*vcategory'; |
||||
const RELATION_TABLE = '*PREFIX*vcategory_to_object'; |
||||
|
||||
const TAG_FAVORITE = '_$!<Favorite>!$_'; |
||||
|
||||
/** |
||||
* Constructor. |
||||
* |
||||
* @param string $user The user whos data the object will operate on. |
||||
*/ |
||||
public function __construct($user, $type, $defaultTags = array()) { |
||||
$this->user = $user; |
||||
$this->type = $type; |
||||
$this->loadTags($defaultTags); |
||||
} |
||||
|
||||
/** |
||||
* Load tags from db. |
||||
* |
||||
* @param string $type The type identifier e.g. 'contact' or 'event'. |
||||
* @param array $defaultTags An array of default tags to be used if none are stored. |
||||
*/ |
||||
protected function loadTags($defaultTags=array()) { |
||||
$this->tags = array(); |
||||
$result = null; |
||||
$sql = 'SELECT `id`, `category` FROM `' . self::TAG_TABLE . '` ' |
||||
. 'WHERE `uid` = ? AND `type` = ? ORDER BY `category`'; |
||||
try { |
||||
$stmt = \OCP\DB::prepare($sql); |
||||
$result = $stmt->execute(array($this->user, $this->type)); |
||||
if (\OCP\DB::isError($result)) { |
||||
\OCP\Util::writeLog('core', __METHOD__. ', DB error: ' . \OCP\DB::getErrorMessage($result), \OCP\Util::ERROR); |
||||
} |
||||
} catch(\Exception $e) { |
||||
\OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), |
||||
\OCP\Util::ERROR); |
||||
} |
||||
|
||||
if(!is_null($result)) { |
||||
while( $row = $result->fetchRow()) { |
||||
$this->tags[$row['id']] = $row['category']; |
||||
} |
||||
} |
||||
|
||||
if(count($defaultTags) > 0 && count($this->tags) === 0) { |
||||
$this->addMultiple($defaultTags, true); |
||||
} |
||||
\OCP\Util::writeLog('core', __METHOD__.', tags: ' . print_r($this->tags, true), |
||||
\OCP\Util::DEBUG); |
||||
|
||||
} |
||||
|
||||
/** |
||||
* Check if any tags are saved for this type and user. |
||||
* |
||||
* @return boolean. |
||||
*/ |
||||
public function isEmpty() { |
||||
$sql = 'SELECT COUNT(*) FROM `' . self::TAG_TABLE . '` ' |
||||
. 'WHERE `uid` = ? AND `type` = ?'; |
||||
try { |
||||
$stmt = \OCP\DB::prepare($sql); |
||||
$result = $stmt->execute(array($this->user, $this->type)); |
||||
if (\OCP\DB::isError($result)) { |
||||
\OCP\Util::writeLog('core', __METHOD__. ', DB error: ' . \OCP\DB::getErrorMessage($result), \OCP\Util::ERROR); |
||||
return false; |
||||
} |
||||
return ((int)$result->fetchOne() === 0); |
||||
} catch(\Exception $e) { |
||||
\OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), |
||||
\OCP\Util::ERROR); |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Get the tags for a specific user. |
||||
* |
||||
* This returns an array with id/name maps: |
||||
* [ |
||||
* ['id' => 0, 'name' = 'First tag'], |
||||
* ['id' => 1, 'name' = 'Second tag'], |
||||
* ] |
||||
* |
||||
* @return array |
||||
*/ |
||||
public function getTags() { |
||||
if(!count($this->tags)) { |
||||
return array(); |
||||
} |
||||
|
||||
$tags = array_values($this->tags); |
||||
uasort($tags, 'strnatcasecmp'); |
||||
$tagMap = array(); |
||||
|
||||
foreach($tags as $tag) { |
||||
if($tag !== self::TAG_FAVORITE) { |
||||
$tagMap[] = array( |
||||
'id' => $this->array_searchi($tag, $this->tags), |
||||
'name' => $tag |
||||
); |
||||
} |
||||
} |
||||
return $tagMap; |
||||
|
||||
} |
||||
|
||||
/** |
||||
* Get the a list if items tagged with $tag. |
||||
* |
||||
* Throws an exception if the tag could not be found. |
||||
* |
||||
* @param string|integer $tag Tag id or name. |
||||
* @return array An array of object ids or false on error. |
||||
*/ |
||||
public function getIdsForTag($tag) { |
||||
$result = null; |
||||
if(is_numeric($tag)) { |
||||
$tagId = $tag; |
||||
} elseif(is_string($tag)) { |
||||
$tag = trim($tag); |
||||
$tagId = $this->array_searchi($tag, $this->tags); |
||||
} |
||||
|
||||
if($tagId === false) { |
||||
$l10n = \OC_L10N::get('core'); |
||||
throw new \Exception( |
||||
$l10n->t('Could not find category "%s"', $tag) |
||||
); |
||||
} |
||||
|
||||
$ids = array(); |
||||
$sql = 'SELECT `objid` FROM `' . self::RELATION_TABLE |
||||
. '` WHERE `categoryid` = ?'; |
||||
|
||||
try { |
||||
$stmt = \OCP\DB::prepare($sql); |
||||
$result = $stmt->execute(array($tagId)); |
||||
if (\OCP\DB::isError($result)) { |
||||
\OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OCP\DB::getErrorMessage($result), \OCP\Util::ERROR); |
||||
return false; |
||||
} |
||||
} catch(\Exception $e) { |
||||
\OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), |
||||
\OCP\Util::ERROR); |
||||
return false; |
||||
} |
||||
|
||||
if(!is_null($result)) { |
||||
while( $row = $result->fetchRow()) { |
||||
$ids[] = (int)$row['objid']; |
||||
} |
||||
} |
||||
|
||||
return $ids; |
||||
} |
||||
|
||||
/** |
||||
* Checks whether a tag is already saved. |
||||
* |
||||
* @param string $name The name to check for. |
||||
* @return bool |
||||
*/ |
||||
public function hasTag($name) { |
||||
return $this->in_arrayi($name, $this->tags); |
||||
} |
||||
|
||||
/** |
||||
* Add a new tag. |
||||
* |
||||
* @param string $name A string with a name of the tag |
||||
* @return int the id of the added tag or false if it already exists. |
||||
*/ |
||||
public function add($name) { |
||||
$name = trim($name); |
||||
|
||||
if($this->hasTag($name)) { |
||||
\OCP\Util::writeLog('core', __METHOD__.', name: ' . $name. ' exists already', \OCP\Util::DEBUG); |
||||
return false; |
||||
} |
||||
try { |
||||
$result = \OCP\DB::insertIfNotExist( |
||||
self::TAG_TABLE, |
||||
array( |
||||
'uid' => $this->user, |
||||
'type' => $this->type, |
||||
'category' => $name, |
||||
) |
||||
); |
||||
if (\OCP\DB::isError($result)) { |
||||
\OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OCP\DB::getErrorMessage($result), \OCP\Util::ERROR); |
||||
return false; |
||||
} elseif((int)$result === 0) { |
||||
\OCP\Util::writeLog('core', __METHOD__.', Tag already exists: ' . $name, \OCP\Util::DEBUG); |
||||
return false; |
||||
} |
||||
} catch(\Exception $e) { |
||||
\OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), |
||||
\OCP\Util::ERROR); |
||||
return false; |
||||
} |
||||
$id = \OCP\DB::insertid(self::TAG_TABLE); |
||||
\OCP\Util::writeLog('core', __METHOD__.', id: ' . $id, \OCP\Util::DEBUG); |
||||
$this->tags[$id] = $name; |
||||
return $id; |
||||
} |
||||
|
||||
/** |
||||
* Rename tag. |
||||
* |
||||
* @param string $from The name of the existing tag |
||||
* @param string $to The new name of the tag. |
||||
* @return bool |
||||
*/ |
||||
public function rename($from, $to) { |
||||
$from = trim($from); |
||||
$to = trim($to); |
||||
$id = $this->array_searchi($from, $this->tags); |
||||
if($id === false) { |
||||
\OCP\Util::writeLog('core', __METHOD__.', tag: ' . $from. ' does not exist', \OCP\Util::DEBUG); |
||||
return false; |
||||
} |
||||
|
||||
$sql = 'UPDATE `' . self::TAG_TABLE . '` SET `category` = ? ' |
||||
. 'WHERE `uid` = ? AND `type` = ? AND `id` = ?'; |
||||
try { |
||||
$stmt = \OCP\DB::prepare($sql); |
||||
$result = $stmt->execute(array($to, $this->user, $this->type, $id)); |
||||
if (\OCP\DB::isError($result)) { |
||||
\OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OCP\DB::getErrorMessage($result), \OCP\Util::ERROR); |
||||
return false; |
||||
} |
||||
} catch(\Exception $e) { |
||||
\OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), |
||||
\OCP\Util::ERROR); |
||||
return false; |
||||
} |
||||
$this->tags[$id] = $to; |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* Add a list of new tags. |
||||
* |
||||
* @param string[] $names A string with a name or an array of strings containing |
||||
* the name(s) of the to add. |
||||
* @param bool $sync When true, save the tags |
||||
* @param int|null $id int Optional object id to add to this|these tag(s) |
||||
* @return bool Returns false on error. |
||||
*/ |
||||
public function addMultiple($names, $sync=false, $id = null) { |
||||
if(!is_array($names)) { |
||||
$names = array($names); |
||||
} |
||||
$names = array_map('trim', $names); |
||||
$newones = array(); |
||||
foreach($names as $name) { |
||||
if(($this->in_arrayi( |
||||
$name, $this->tags) == false) && $name !== '') { |
||||
$newones[] = $name; |
||||
} |
||||
if(!is_null($id) ) { |
||||
// Insert $objectid, $categoryid pairs if not exist. |
||||
self::$relations[] = array('objid' => $id, 'tag' => $name); |
||||
} |
||||
} |
||||
$this->tags = array_merge($this->tags, $newones); |
||||
if($sync === true) { |
||||
$this->save(); |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* Save the list of tags and their object relations |
||||
*/ |
||||
protected function save() { |
||||
if(is_array($this->tags)) { |
||||
foreach($this->tags as $tag) { |
||||
try { |
||||
\OCP\DB::insertIfNotExist(self::TAG_TABLE, |
||||
array( |
||||
'uid' => $this->user, |
||||
'type' => $this->type, |
||||
'category' => $tag, |
||||
)); |
||||
} catch(\Exception $e) { |
||||
\OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), |
||||
\OCP\Util::ERROR); |
||||
} |
||||
} |
||||
// reload tags to get the proper ids. |
||||
$this->loadTags(); |
||||
// Loop through temporarily cached objectid/tagname pairs |
||||
// and save relations. |
||||
$tags = $this->tags; |
||||
// For some reason this is needed or array_search(i) will return 0..? |
||||
ksort($tags); |
||||
foreach(self::$relations as $relation) { |
||||
$tagId = $this->array_searchi($relation['tag'], $tags); |
||||
\OCP\Util::writeLog('core', __METHOD__ . 'catid, ' . $relation['tag'] . ' ' . $tagId, \OCP\Util::DEBUG); |
||||
if($tagId) { |
||||
try { |
||||
\OCP\DB::insertIfNotExist(self::RELATION_TABLE, |
||||
array( |
||||
'objid' => $relation['objid'], |
||||
'categoryid' => $tagId, |
||||
'type' => $this->type, |
||||
)); |
||||
} catch(\Exception $e) { |
||||
\OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), |
||||
\OCP\Util::ERROR); |
||||
} |
||||
} |
||||
} |
||||
self::$relations = array(); // reset |
||||
} else { |
||||
\OCP\Util::writeLog('core', __METHOD__.', $this->tags is not an array! ' |
||||
. print_r($this->tags, true), \OCP\Util::ERROR); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Delete tags and tag/object relations for a user. |
||||
* |
||||
* For hooking up on post_deleteUser |
||||
* |
||||
* @param array |
||||
*/ |
||||
public static function post_deleteUser($arguments) { |
||||
// Find all objectid/tagId pairs. |
||||
$result = null; |
||||
try { |
||||
$stmt = \OCP\DB::prepare('SELECT `id` FROM `' . self::TAG_TABLE . '` ' |
||||
. 'WHERE `uid` = ?'); |
||||
$result = $stmt->execute(array($arguments['uid'])); |
||||
if (\OCP\DB::isError($result)) { |
||||
\OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OCP\DB::getErrorMessage($result), \OCP\Util::ERROR); |
||||
} |
||||
} catch(\Exception $e) { |
||||
\OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), |
||||
\OCP\Util::ERROR); |
||||
} |
||||
|
||||
if(!is_null($result)) { |
||||
try { |
||||
$stmt = \OCP\DB::prepare('DELETE FROM `' . self::RELATION_TABLE . '` ' |
||||
. 'WHERE `categoryid` = ?'); |
||||
while( $row = $result->fetchRow()) { |
||||
try { |
||||
$stmt->execute(array($row['id'])); |
||||
} catch(\Exception $e) { |
||||
\OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), |
||||
\OCP\Util::ERROR); |
||||
} |
||||
} |
||||
} catch(\Exception $e) { |
||||
\OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), |
||||
\OCP\Util::ERROR); |
||||
} |
||||
} |
||||
try { |
||||
$stmt = \OCP\DB::prepare('DELETE FROM `' . self::TAG_TABLE . '` ' |
||||
. 'WHERE `uid` = ?'); |
||||
$result = $stmt->execute(array($arguments['uid'])); |
||||
if (\OCP\DB::isError($result)) { |
||||
\OCP\Util::writeLog('core', __METHOD__. ', DB error: ' . \OCP\DB::getErrorMessage($result), \OCP\Util::ERROR); |
||||
} |
||||
} catch(\Exception $e) { |
||||
\OCP\Util::writeLog('core', __METHOD__ . ', exception: ' |
||||
. $e->getMessage(), \OCP\Util::ERROR); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Delete tag/object relations from the db |
||||
* |
||||
* @param array $ids The ids of the objects |
||||
* @return boolean Returns false on error. |
||||
*/ |
||||
public function purgeObjects(array $ids) { |
||||
if(count($ids) === 0) { |
||||
// job done ;) |
||||
return true; |
||||
} |
||||
$updates = $ids; |
||||
try { |
||||
$query = 'DELETE FROM `' . self::RELATION_TABLE . '` '; |
||||
$query .= 'WHERE `objid` IN (' . str_repeat('?,', count($ids)-1) . '?) '; |
||||
$query .= 'AND `type`= ?'; |
||||
$updates[] = $this->type; |
||||
$stmt = \OCP\DB::prepare($query); |
||||
$result = $stmt->execute($updates); |
||||
if (\OCP\DB::isError($result)) { |
||||
\OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OCP\DB::getErrorMessage($result), \OCP\Util::ERROR); |
||||
return false; |
||||
} |
||||
} catch(\Exception $e) { |
||||
\OCP\Util::writeLog('core', __METHOD__.', exception: ' . $e->getMessage(), |
||||
\OCP\Util::ERROR); |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* Get favorites for an object type |
||||
* |
||||
* @return array An array of object ids. |
||||
*/ |
||||
public function getFavorites() { |
||||
try { |
||||
return $this->getIdsForTag(self::TAG_FAVORITE); |
||||
} catch(\Exception $e) { |
||||
\OCP\Util::writeLog('core', __METHOD__.', exception: ' . $e->getMessage(), |
||||
\OCP\Util::ERROR); |
||||
return array(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Add an object to favorites |
||||
* |
||||
* @param int $objid The id of the object |
||||
* @return boolean |
||||
*/ |
||||
public function addToFavorites($objid) { |
||||
if(!$this->hasTag(self::TAG_FAVORITE)) { |
||||
$this->add(self::TAG_FAVORITE, true); |
||||
} |
||||
return $this->tagAs($objid, self::TAG_FAVORITE, $this->type); |
||||
} |
||||
|
||||
/** |
||||
* Remove an object from favorites |
||||
* |
||||
* @param int $objid The id of the object |
||||
* @return boolean |
||||
*/ |
||||
public function removeFromFavorites($objid) { |
||||
return $this->unTag($objid, self::TAG_FAVORITE, $this->type); |
||||
} |
||||
|
||||
/** |
||||
* Creates a tag/object relation. |
||||
* |
||||
* @param int $objid The id of the object |
||||
* @param int|string $tag The id or name of the tag |
||||
* @return boolean Returns false on database error. |
||||
*/ |
||||
public function tagAs($objid, $tag) { |
||||
if(is_string($tag) && !is_numeric($tag)) { |
||||
$tag = trim($tag); |
||||
if(!$this->hasTag($tag)) { |
||||
$this->add($tag, true); |
||||
} |
||||
$tagId = $this->array_searchi($tag, $this->tags); |
||||
} else { |
||||
$tagId = $tag; |
||||
} |
||||
try { |
||||
\OCP\DB::insertIfNotExist(self::RELATION_TABLE, |
||||
array( |
||||
'objid' => $objid, |
||||
'categoryid' => $tagId, |
||||
'type' => $this->type, |
||||
)); |
||||
} catch(\Exception $e) { |
||||
\OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), |
||||
\OCP\Util::ERROR); |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* Delete single tag/object relation from the db |
||||
* |
||||
* @param int $objid The id of the object |
||||
* @param int|string $tag The id or name of the tag |
||||
* @return boolean |
||||
*/ |
||||
public function unTag($objid, $tag) { |
||||
if(is_string($tag) && !is_numeric($tag)) { |
||||
$tag = trim($tag); |
||||
$tagId = $this->array_searchi($tag, $this->tags); |
||||
} else { |
||||
$tagId = $tag; |
||||
} |
||||
|
||||
try { |
||||
$sql = 'DELETE FROM `' . self::RELATION_TABLE . '` ' |
||||
. 'WHERE `objid` = ? AND `categoryid` = ? AND `type` = ?'; |
||||
$stmt = \OCP\DB::prepare($sql); |
||||
$stmt->execute(array($objid, $tagId, $this->type)); |
||||
} catch(\Exception $e) { |
||||
\OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), |
||||
\OCP\Util::ERROR); |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* Delete tags from the |
||||
* |
||||
* @param string[] $names An array of tags to delete |
||||
* @return bool Returns false on error |
||||
*/ |
||||
public function delete($names) { |
||||
if(!is_array($names)) { |
||||
$names = array($names); |
||||
} |
||||
|
||||
$names = array_map('trim', $names); |
||||
|
||||
\OCP\Util::writeLog('core', __METHOD__ . ', before: ' |
||||
. print_r($this->tags, true), \OCP\Util::DEBUG); |
||||
foreach($names as $name) { |
||||
$id = null; |
||||
|
||||
if($this->hasTag($name)) { |
||||
$id = $this->array_searchi($name, $this->tags); |
||||
unset($this->tags[$id]); |
||||
} |
||||
try { |
||||
$stmt = \OCP\DB::prepare('DELETE FROM `' . self::TAG_TABLE . '` WHERE ' |
||||
. '`uid` = ? AND `type` = ? AND `category` = ?'); |
||||
$result = $stmt->execute(array($this->user, $this->type, $name)); |
||||
if (\OCP\DB::isError($result)) { |
||||
\OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OCP\DB::getErrorMessage($result), \OCP\Util::ERROR); |
||||
} |
||||
} catch(\Exception $e) { |
||||
\OCP\Util::writeLog('core', __METHOD__ . ', exception: ' |
||||
. $e->getMessage(), \OCP\Util::ERROR); |
||||
return false; |
||||
} |
||||
if(!is_null($id) && $id !== false) { |
||||
try { |
||||
$sql = 'DELETE FROM `' . self::RELATION_TABLE . '` ' |
||||
. 'WHERE `categoryid` = ?'; |
||||
$stmt = \OCP\DB::prepare($sql); |
||||
$result = $stmt->execute(array($id)); |
||||
if (\OCP\DB::isError($result)) { |
||||
\OCP\Util::writeLog('core', |
||||
__METHOD__. 'DB error: ' . \OCP\DB::getErrorMessage($result), |
||||
\OCP\Util::ERROR); |
||||
return false; |
||||
} |
||||
} catch(\Exception $e) { |
||||
\OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), |
||||
\OCP\Util::ERROR); |
||||
return false; |
||||
} |
||||
} |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
// case-insensitive in_array |
||||
private function in_arrayi($needle, $haystack) { |
||||
if(!is_array($haystack)) { |
||||
return false; |
||||
} |
||||
return in_array(strtolower($needle), array_map('strtolower', $haystack)); |
||||
} |
||||
|
||||
// case-insensitive array_search |
||||
private function array_searchi($needle, $haystack) { |
||||
if(!is_array($haystack)) { |
||||
return false; |
||||
} |
||||
return array_search(strtolower($needle), array_map('strtolower', $haystack)); |
||||
} |
||||
} |
@ -1,821 +0,0 @@ |
||||
<?php |
||||
/** |
||||
* ownCloud |
||||
* |
||||
* @author Thomas Tanghus |
||||
* @copyright 2012 Thomas Tanghus <thomas@tanghus.net> |
||||
* @copyright 2012 Bart Visscher bartv@thisnet.nl |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
OC_Hook::connect('OC_User', 'post_deleteUser', 'OC_VCategories', 'post_deleteUser'); |
||||
|
||||
/** |
||||
* Class for easy access to categories in VCARD, VEVENT, VTODO and VJOURNAL. |
||||
* A Category can be e.g. 'Family', 'Work', 'Chore', 'Special Occation' or |
||||
* anything else that is either parsed from a vobject or that the user chooses |
||||
* to add. |
||||
* Category names are not case-sensitive, but will be saved with the case they |
||||
* are entered in. If a user already has a category 'family' for a type, and |
||||
* tries to add a category named 'Family' it will be silently ignored. |
||||
*/ |
||||
class OC_VCategories { |
||||
|
||||
/** |
||||
* Categories |
||||
*/ |
||||
private $categories = array(); |
||||
|
||||
/** |
||||
* Used for storing objectid/categoryname pairs while rescanning. |
||||
*/ |
||||
private static $relations = array(); |
||||
|
||||
private $type = null; |
||||
private $user = null; |
||||
|
||||
const CATEGORY_TABLE = '*PREFIX*vcategory'; |
||||
const RELATION_TABLE = '*PREFIX*vcategory_to_object'; |
||||
|
||||
const CATEGORY_FAVORITE = '_$!<Favorite>!$_'; |
||||
|
||||
const FORMAT_LIST = 0; |
||||
const FORMAT_MAP = 1; |
||||
|
||||
/** |
||||
* @brief Constructor. |
||||
* @param $type The type identifier e.g. 'contact' or 'event'. |
||||
* @param $user The user whos data the object will operate on. This |
||||
* parameter should normally be omitted but to make an app able to |
||||
* update categories for all users it is made possible to provide it. |
||||
* @param $defcategories An array of default categories to be used if none is stored. |
||||
*/ |
||||
public function __construct($type, $user=null, $defcategories=array()) { |
||||
$this->type = $type; |
||||
$this->user = is_null($user) ? OC_User::getUser() : $user; |
||||
|
||||
$this->loadCategories(); |
||||
OCP\Util::writeLog('core', __METHOD__ . ', categories: ' |
||||
. print_r($this->categories, true), |
||||
OCP\Util::DEBUG |
||||
); |
||||
|
||||
if($defcategories && count($this->categories) === 0) { |
||||
$this->addMulti($defcategories, true); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @brief Load categories from db. |
||||
*/ |
||||
private function loadCategories() { |
||||
$this->categories = array(); |
||||
$result = null; |
||||
$sql = 'SELECT `id`, `category` FROM `' . self::CATEGORY_TABLE . '` ' |
||||
. 'WHERE `uid` = ? AND `type` = ? ORDER BY `category`'; |
||||
try { |
||||
$stmt = OCP\DB::prepare($sql); |
||||
$result = $stmt->execute(array($this->user, $this->type)); |
||||
if (OC_DB::isError($result)) { |
||||
OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR); |
||||
} |
||||
} catch(Exception $e) { |
||||
OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), |
||||
OCP\Util::ERROR); |
||||
} |
||||
|
||||
if(!is_null($result)) { |
||||
while( $row = $result->fetchRow()) { |
||||
// The keys are prefixed because array_search wouldn't work otherwise :-/ |
||||
$this->categories[$row['id']] = $row['category']; |
||||
} |
||||
} |
||||
OCP\Util::writeLog('core', __METHOD__.', categories: ' . print_r($this->categories, true), |
||||
OCP\Util::DEBUG); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @brief Check if any categories are saved for this type and user. |
||||
* @returns boolean. |
||||
* @param $type The type identifier e.g. 'contact' or 'event'. |
||||
* @param $user The user whos categories will be checked. If not set current user will be used. |
||||
*/ |
||||
public static function isEmpty($type, $user = null) { |
||||
$user = is_null($user) ? OC_User::getUser() : $user; |
||||
$sql = 'SELECT COUNT(*) FROM `' . self::CATEGORY_TABLE . '` ' |
||||
. 'WHERE `uid` = ? AND `type` = ?'; |
||||
try { |
||||
$stmt = OCP\DB::prepare($sql); |
||||
$result = $stmt->execute(array($user, $type)); |
||||
if (OC_DB::isError($result)) { |
||||
OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR); |
||||
return false; |
||||
} |
||||
return ($result->numRows() === 0); |
||||
} catch(Exception $e) { |
||||
OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), |
||||
OCP\Util::ERROR); |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @brief Get the categories for a specific user. |
||||
* @param |
||||
* @returns array containing the categories as strings. |
||||
*/ |
||||
public function categories($format = null) { |
||||
if(!$this->categories) { |
||||
return array(); |
||||
} |
||||
$categories = array_values($this->categories); |
||||
uasort($categories, 'strnatcasecmp'); |
||||
if($format == self::FORMAT_MAP) { |
||||
$catmap = array(); |
||||
foreach($categories as $category) { |
||||
if($category !== self::CATEGORY_FAVORITE) { |
||||
$catmap[] = array( |
||||
'id' => $this->array_searchi($category, $this->categories), |
||||
'name' => $category |
||||
); |
||||
} |
||||
} |
||||
return $catmap; |
||||
} |
||||
|
||||
// Don't add favorites to normal categories. |
||||
$favpos = array_search(self::CATEGORY_FAVORITE, $categories); |
||||
if($favpos !== false) { |
||||
return array_splice($categories, $favpos); |
||||
} else { |
||||
return $categories; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Get the a list if items belonging to $category. |
||||
* |
||||
* Throws an exception if the category could not be found. |
||||
* |
||||
* @param string|integer $category Category id or name. |
||||
* @returns array An array of object ids or false on error. |
||||
*/ |
||||
public function idsForCategory($category) { |
||||
$result = null; |
||||
if(is_numeric($category)) { |
||||
$catid = $category; |
||||
} elseif(is_string($category)) { |
||||
$catid = $this->array_searchi($category, $this->categories); |
||||
} |
||||
OCP\Util::writeLog('core', __METHOD__.', category: '.$catid.' '.$category, OCP\Util::DEBUG); |
||||
if($catid === false) { |
||||
$l10n = OC_L10N::get('core'); |
||||
throw new Exception( |
||||
$l10n->t('Could not find category "%s"', $category) |
||||
); |
||||
} |
||||
|
||||
$ids = array(); |
||||
$sql = 'SELECT `objid` FROM `' . self::RELATION_TABLE |
||||
. '` WHERE `categoryid` = ?'; |
||||
|
||||
try { |
||||
$stmt = OCP\DB::prepare($sql); |
||||
$result = $stmt->execute(array($catid)); |
||||
if (OC_DB::isError($result)) { |
||||
OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR); |
||||
return false; |
||||
} |
||||
} catch(Exception $e) { |
||||
OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), |
||||
OCP\Util::ERROR); |
||||
return false; |
||||
} |
||||
|
||||
if(!is_null($result)) { |
||||
while( $row = $result->fetchRow()) { |
||||
$ids[] = (int)$row['objid']; |
||||
} |
||||
} |
||||
|
||||
return $ids; |
||||
} |
||||
|
||||
/** |
||||
* Get the a list if items belonging to $category. |
||||
* |
||||
* Throws an exception if the category could not be found. |
||||
* |
||||
* @param string|integer $category Category id or name. |
||||
* @param array $tableinfo Array in the form {'tablename' => table, 'fields' => ['field1', 'field2']} |
||||
* @param int $limit |
||||
* @param int $offset |
||||
* |
||||
* This generic method queries a table assuming that the id |
||||
* field is called 'id' and the table name provided is in |
||||
* the form '*PREFIX*table_name'. |
||||
* |
||||
* If the category name cannot be resolved an exception is thrown. |
||||
* |
||||
* TODO: Maybe add the getting permissions for objects? |
||||
* |
||||
* @returns array containing the resulting items or false on error. |
||||
*/ |
||||
public function itemsForCategory($category, $tableinfo, $limit = null, $offset = null) { |
||||
$result = null; |
||||
if(is_numeric($category)) { |
||||
$catid = $category; |
||||
} elseif(is_string($category)) { |
||||
$catid = $this->array_searchi($category, $this->categories); |
||||
} |
||||
OCP\Util::writeLog('core', __METHOD__.', category: '.$catid.' '.$category, OCP\Util::DEBUG); |
||||
if($catid === false) { |
||||
$l10n = OC_L10N::get('core'); |
||||
throw new Exception( |
||||
$l10n->t('Could not find category "%s"', $category) |
||||
); |
||||
} |
||||
$fields = ''; |
||||
foreach($tableinfo['fields'] as $field) { |
||||
$fields .= '`' . $tableinfo['tablename'] . '`.`' . $field . '`,'; |
||||
} |
||||
$fields = substr($fields, 0, -1); |
||||
|
||||
$items = array(); |
||||
$sql = 'SELECT `' . self::RELATION_TABLE . '`.`categoryid`, ' . $fields |
||||
. ' FROM `' . $tableinfo['tablename'] . '` JOIN `' |
||||
. self::RELATION_TABLE . '` ON `' . $tableinfo['tablename'] |
||||
. '`.`id` = `' . self::RELATION_TABLE . '`.`objid` WHERE `' |
||||
. self::RELATION_TABLE . '`.`categoryid` = ?'; |
||||
|
||||
try { |
||||
$stmt = OCP\DB::prepare($sql, $limit, $offset); |
||||
$result = $stmt->execute(array($catid)); |
||||
if (OC_DB::isError($result)) { |
||||
OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR); |
||||
return false; |
||||
} |
||||
} catch(Exception $e) { |
||||
OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), |
||||
OCP\Util::ERROR); |
||||
return false; |
||||
} |
||||
|
||||
if(!is_null($result)) { |
||||
while( $row = $result->fetchRow()) { |
||||
$items[] = $row; |
||||
} |
||||
} |
||||
//OCP\Util::writeLog('core', __METHOD__.', count: ' . count($items), OCP\Util::DEBUG); |
||||
//OCP\Util::writeLog('core', __METHOD__.', sql: ' . $sql, OCP\Util::DEBUG); |
||||
|
||||
return $items; |
||||
} |
||||
|
||||
/** |
||||
* @brief Checks whether a category is already saved. |
||||
* @param $name The name to check for. |
||||
* @returns bool |
||||
*/ |
||||
public function hasCategory($name) { |
||||
return $this->in_arrayi($name, $this->categories); |
||||
} |
||||
|
||||
/** |
||||
* @brief Add a new category. |
||||
* @param $name A string with a name of the category |
||||
* @returns int the id of the added category or false if it already exists. |
||||
*/ |
||||
public function add($name) { |
||||
OCP\Util::writeLog('core', __METHOD__.', name: ' . $name, OCP\Util::DEBUG); |
||||
if($this->hasCategory($name)) { |
||||
OCP\Util::writeLog('core', __METHOD__.', name: ' . $name. ' exists already', OCP\Util::DEBUG); |
||||
return false; |
||||
} |
||||
try { |
||||
OCP\DB::insertIfNotExist(self::CATEGORY_TABLE, |
||||
array( |
||||
'uid' => $this->user, |
||||
'type' => $this->type, |
||||
'category' => $name, |
||||
)); |
||||
} catch(Exception $e) { |
||||
OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), |
||||
OCP\Util::ERROR); |
||||
return false; |
||||
} |
||||
$id = OCP\DB::insertid(self::CATEGORY_TABLE); |
||||
OCP\Util::writeLog('core', __METHOD__.', id: ' . $id, OCP\Util::DEBUG); |
||||
$this->categories[$id] = $name; |
||||
return $id; |
||||
} |
||||
|
||||
/** |
||||
* @brief Rename category. |
||||
* @param string $from The name of the existing category |
||||
* @param string $to The new name of the category. |
||||
* @returns bool |
||||
*/ |
||||
public function rename($from, $to) { |
||||
$id = $this->array_searchi($from, $this->categories); |
||||
if($id === false) { |
||||
OCP\Util::writeLog('core', __METHOD__.', category: ' . $from. ' does not exist', OCP\Util::DEBUG); |
||||
return false; |
||||
} |
||||
|
||||
$sql = 'UPDATE `' . self::CATEGORY_TABLE . '` SET `category` = ? ' |
||||
. 'WHERE `uid` = ? AND `type` = ? AND `id` = ?'; |
||||
try { |
||||
$stmt = OCP\DB::prepare($sql); |
||||
$result = $stmt->execute(array($to, $this->user, $this->type, $id)); |
||||
if (OC_DB::isError($result)) { |
||||
OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR); |
||||
return false; |
||||
} |
||||
} catch(Exception $e) { |
||||
OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), |
||||
OCP\Util::ERROR); |
||||
return false; |
||||
} |
||||
$this->categories[$id] = $to; |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* @brief Add a new category. |
||||
* @param $names A string with a name or an array of strings containing |
||||
* the name(s) of the categor(y|ies) to add. |
||||
* @param $sync bool When true, save the categories |
||||
* @param $id int Optional object id to add to this|these categor(y|ies) |
||||
* @returns bool Returns false on error. |
||||
*/ |
||||
public function addMulti($names, $sync=false, $id = null) { |
||||
if(!is_array($names)) { |
||||
$names = array($names); |
||||
} |
||||
$names = array_map('trim', $names); |
||||
$newones = array(); |
||||
foreach($names as $name) { |
||||
if(($this->in_arrayi( |
||||
$name, $this->categories) == false) && $name != '') { |
||||
$newones[] = $name; |
||||
} |
||||
if(!is_null($id) ) { |
||||
// Insert $objectid, $categoryid pairs if not exist. |
||||
self::$relations[] = array('objid' => $id, 'category' => $name); |
||||
} |
||||
} |
||||
$this->categories = array_merge($this->categories, $newones); |
||||
if($sync === true) { |
||||
$this->save(); |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* @brief Extracts categories from a vobject and add the ones not already present. |
||||
* @param $vobject The instance of OC_VObject to load the categories from. |
||||
*/ |
||||
public function loadFromVObject($id, $vobject, $sync=false) { |
||||
$this->addMulti($vobject->getAsArray('CATEGORIES'), $sync, $id); |
||||
} |
||||
|
||||
/** |
||||
* @brief Reset saved categories and rescan supplied vobjects for categories. |
||||
* @param $objects An array of vobjects (as text). |
||||
* To get the object array, do something like: |
||||
* // For Addressbook: |
||||
* $categories = new OC_VCategories('contacts'); |
||||
* $stmt = OC_DB::prepare( 'SELECT `carddata` FROM `*PREFIX*contacts_cards`' ); |
||||
* $result = $stmt->execute(); |
||||
* $objects = array(); |
||||
* if(!is_null($result)) { |
||||
* while( $row = $result->fetchRow()){ |
||||
* $objects[] = array($row['id'], $row['carddata']); |
||||
* } |
||||
* } |
||||
* $categories->rescan($objects); |
||||
*/ |
||||
public function rescan($objects, $sync=true, $reset=true) { |
||||
|
||||
if($reset === true) { |
||||
$result = null; |
||||
// Find all objectid/categoryid pairs. |
||||
try { |
||||
$stmt = OCP\DB::prepare('SELECT `id` FROM `' . self::CATEGORY_TABLE . '` ' |
||||
. 'WHERE `uid` = ? AND `type` = ?'); |
||||
$result = $stmt->execute(array($this->user, $this->type)); |
||||
if (OC_DB::isError($result)) { |
||||
OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR); |
||||
return false; |
||||
} |
||||
} catch(Exception $e) { |
||||
OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), |
||||
OCP\Util::ERROR); |
||||
} |
||||
|
||||
// And delete them. |
||||
if(!is_null($result)) { |
||||
$stmt = OCP\DB::prepare('DELETE FROM `' . self::RELATION_TABLE . '` ' |
||||
. 'WHERE `categoryid` = ? AND `type`= ?'); |
||||
while( $row = $result->fetchRow()) { |
||||
$stmt->execute(array($row['id'], $this->type)); |
||||
} |
||||
} |
||||
try { |
||||
$stmt = OCP\DB::prepare('DELETE FROM `' . self::CATEGORY_TABLE . '` ' |
||||
. 'WHERE `uid` = ? AND `type` = ?'); |
||||
$result = $stmt->execute(array($this->user, $this->type)); |
||||
if (OC_DB::isError($result)) { |
||||
OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR); |
||||
return; |
||||
} |
||||
} catch(Exception $e) { |
||||
OCP\Util::writeLog('core', __METHOD__ . ', exception: ' |
||||
. $e->getMessage(), OCP\Util::ERROR); |
||||
return; |
||||
} |
||||
$this->categories = array(); |
||||
} |
||||
// Parse all the VObjects |
||||
foreach($objects as $object) { |
||||
$vobject = OC_VObject::parse($object[1]); |
||||
if(!is_null($vobject)) { |
||||
// Load the categories |
||||
$this->loadFromVObject($object[0], $vobject, $sync); |
||||
} else { |
||||
OC_Log::write('core', __METHOD__ . ', unable to parse. ID: ' . ', ' |
||||
. substr($object, 0, 100) . '(...)', OC_Log::DEBUG); |
||||
} |
||||
} |
||||
$this->save(); |
||||
} |
||||
|
||||
/** |
||||
* @brief Save the list with categories |
||||
*/ |
||||
private function save() { |
||||
if(is_array($this->categories)) { |
||||
foreach($this->categories as $category) { |
||||
try { |
||||
OCP\DB::insertIfNotExist(self::CATEGORY_TABLE, |
||||
array( |
||||
'uid' => $this->user, |
||||
'type' => $this->type, |
||||
'category' => $category, |
||||
)); |
||||
} catch(Exception $e) { |
||||
OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), |
||||
OCP\Util::ERROR); |
||||
} |
||||
} |
||||
// reload categories to get the proper ids. |
||||
$this->loadCategories(); |
||||
// Loop through temporarily cached objectid/categoryname pairs |
||||
// and save relations. |
||||
$categories = $this->categories; |
||||
// For some reason this is needed or array_search(i) will return 0..? |
||||
ksort($categories); |
||||
foreach(self::$relations as $relation) { |
||||
$catid = $this->array_searchi($relation['category'], $categories); |
||||
OC_Log::write('core', __METHOD__ . 'catid, ' . $relation['category'] . ' ' . $catid, OC_Log::DEBUG); |
||||
if($catid) { |
||||
try { |
||||
OCP\DB::insertIfNotExist(self::RELATION_TABLE, |
||||
array( |
||||
'objid' => $relation['objid'], |
||||
'categoryid' => $catid, |
||||
'type' => $this->type, |
||||
)); |
||||
} catch(Exception $e) { |
||||
OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), |
||||
OCP\Util::ERROR); |
||||
} |
||||
} |
||||
} |
||||
self::$relations = array(); // reset |
||||
} else { |
||||
OC_Log::write('core', __METHOD__.', $this->categories is not an array! ' |
||||
. print_r($this->categories, true), OC_Log::ERROR); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @brief Delete categories and category/object relations for a user. |
||||
* For hooking up on post_deleteUser |
||||
* @param string $uid The user id for which entries should be purged. |
||||
*/ |
||||
public static function post_deleteUser($arguments) { |
||||
// Find all objectid/categoryid pairs. |
||||
$result = null; |
||||
try { |
||||
$stmt = OCP\DB::prepare('SELECT `id` FROM `' . self::CATEGORY_TABLE . '` ' |
||||
. 'WHERE `uid` = ?'); |
||||
$result = $stmt->execute(array($arguments['uid'])); |
||||
if (OC_DB::isError($result)) { |
||||
OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR); |
||||
} |
||||
} catch(Exception $e) { |
||||
OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), |
||||
OCP\Util::ERROR); |
||||
} |
||||
|
||||
if(!is_null($result)) { |
||||
try { |
||||
$stmt = OCP\DB::prepare('DELETE FROM `' . self::RELATION_TABLE . '` ' |
||||
. 'WHERE `categoryid` = ?'); |
||||
while( $row = $result->fetchRow()) { |
||||
try { |
||||
$stmt->execute(array($row['id'])); |
||||
} catch(Exception $e) { |
||||
OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), |
||||
OCP\Util::ERROR); |
||||
} |
||||
} |
||||
} catch(Exception $e) { |
||||
OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), |
||||
OCP\Util::ERROR); |
||||
} |
||||
} |
||||
try { |
||||
$stmt = OCP\DB::prepare('DELETE FROM `' . self::CATEGORY_TABLE . '` ' |
||||
. 'WHERE `uid` = ?'); |
||||
$result = $stmt->execute(array($arguments['uid'])); |
||||
if (OC_DB::isError($result)) { |
||||
OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR); |
||||
} |
||||
} catch(Exception $e) { |
||||
OCP\Util::writeLog('core', __METHOD__ . ', exception: ' |
||||
. $e->getMessage(), OCP\Util::ERROR); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @brief Delete category/object relations from the db |
||||
* @param array $ids The ids of the objects |
||||
* @param string $type The type of object (event/contact/task/journal). |
||||
* Defaults to the type set in the instance |
||||
* @returns boolean Returns false on error. |
||||
*/ |
||||
public function purgeObjects(array $ids, $type = null) { |
||||
$type = is_null($type) ? $this->type : $type; |
||||
if(count($ids) === 0) { |
||||
// job done ;) |
||||
return true; |
||||
} |
||||
$updates = $ids; |
||||
try { |
||||
$query = 'DELETE FROM `' . self::RELATION_TABLE . '` '; |
||||
$query .= 'WHERE `objid` IN (' . str_repeat('?,', count($ids)-1) . '?) '; |
||||
$query .= 'AND `type`= ?'; |
||||
$updates[] = $type; |
||||
$stmt = OCP\DB::prepare($query); |
||||
$result = $stmt->execute($updates); |
||||
if (OC_DB::isError($result)) { |
||||
OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR); |
||||
return false; |
||||
} |
||||
} catch(Exception $e) { |
||||
OCP\Util::writeLog('core', __METHOD__.', exception: ' . $e->getMessage(), |
||||
OCP\Util::ERROR); |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* Get favorites for an object type |
||||
* |
||||
* @param string $type The type of object (event/contact/task/journal). |
||||
* Defaults to the type set in the instance |
||||
* @returns array An array of object ids. |
||||
*/ |
||||
public function getFavorites($type = null) { |
||||
$type = is_null($type) ? $this->type : $type; |
||||
|
||||
try { |
||||
return $this->idsForCategory(self::CATEGORY_FAVORITE); |
||||
} catch(Exception $e) { |
||||
// No favorites |
||||
return array(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Add an object to favorites |
||||
* |
||||
* @param int $objid The id of the object |
||||
* @param string $type The type of object (event/contact/task/journal). |
||||
* Defaults to the type set in the instance |
||||
* @returns boolean |
||||
*/ |
||||
public function addToFavorites($objid, $type = null) { |
||||
$type = is_null($type) ? $this->type : $type; |
||||
if(!$this->hasCategory(self::CATEGORY_FAVORITE)) { |
||||
$this->add(self::CATEGORY_FAVORITE, true); |
||||
} |
||||
return $this->addToCategory($objid, self::CATEGORY_FAVORITE, $type); |
||||
} |
||||
|
||||
/** |
||||
* Remove an object from favorites |
||||
* |
||||
* @param int $objid The id of the object |
||||
* @param string $type The type of object (event/contact/task/journal). |
||||
* Defaults to the type set in the instance |
||||
* @returns boolean |
||||
*/ |
||||
public function removeFromFavorites($objid, $type = null) { |
||||
$type = is_null($type) ? $this->type : $type; |
||||
return $this->removeFromCategory($objid, self::CATEGORY_FAVORITE, $type); |
||||
} |
||||
|
||||
/** |
||||
* @brief Creates a category/object relation. |
||||
* @param int $objid The id of the object |
||||
* @param int|string $category The id or name of the category |
||||
* @param string $type The type of object (event/contact/task/journal). |
||||
* Defaults to the type set in the instance |
||||
* @returns boolean Returns false on database error. |
||||
*/ |
||||
public function addToCategory($objid, $category, $type = null) { |
||||
$type = is_null($type) ? $this->type : $type; |
||||
if(is_string($category) && !is_numeric($category)) { |
||||
if(!$this->hasCategory($category)) { |
||||
$this->add($category, true); |
||||
} |
||||
$categoryid = $this->array_searchi($category, $this->categories); |
||||
} else { |
||||
$categoryid = $category; |
||||
} |
||||
try { |
||||
OCP\DB::insertIfNotExist(self::RELATION_TABLE, |
||||
array( |
||||
'objid' => $objid, |
||||
'categoryid' => $categoryid, |
||||
'type' => $type, |
||||
)); |
||||
} catch(Exception $e) { |
||||
OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), |
||||
OCP\Util::ERROR); |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* @brief Delete single category/object relation from the db |
||||
* @param int $objid The id of the object |
||||
* @param int|string $category The id or name of the category |
||||
* @param string $type The type of object (event/contact/task/journal). |
||||
* Defaults to the type set in the instance |
||||
* @returns boolean |
||||
*/ |
||||
public function removeFromCategory($objid, $category, $type = null) { |
||||
$type = is_null($type) ? $this->type : $type; |
||||
$categoryid = (is_string($category) && !is_numeric($category)) |
||||
? $this->array_searchi($category, $this->categories) |
||||
: $category; |
||||
try { |
||||
$sql = 'DELETE FROM `' . self::RELATION_TABLE . '` ' |
||||
. 'WHERE `objid` = ? AND `categoryid` = ? AND `type` = ?'; |
||||
OCP\Util::writeLog('core', __METHOD__.', sql: ' . $objid . ' ' . $categoryid . ' ' . $type, |
||||
OCP\Util::DEBUG); |
||||
$stmt = OCP\DB::prepare($sql); |
||||
$stmt->execute(array($objid, $categoryid, $type)); |
||||
} catch(Exception $e) { |
||||
OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), |
||||
OCP\Util::ERROR); |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* @brief Delete categories from the db and from all the vobject supplied |
||||
* @param $names An array of categories to delete |
||||
* @param $objects An array of arrays with [id,vobject] (as text) pairs suitable for updating the apps object table. |
||||
*/ |
||||
public function delete($names, array &$objects=null) { |
||||
if(!is_array($names)) { |
||||
$names = array($names); |
||||
} |
||||
|
||||
OC_Log::write('core', __METHOD__ . ', before: ' |
||||
. print_r($this->categories, true), OC_Log::DEBUG); |
||||
foreach($names as $name) { |
||||
$id = null; |
||||
OC_Log::write('core', __METHOD__.', '.$name, OC_Log::DEBUG); |
||||
if($this->hasCategory($name)) { |
||||
$id = $this->array_searchi($name, $this->categories); |
||||
unset($this->categories[$id]); |
||||
} |
||||
try { |
||||
$stmt = OCP\DB::prepare('DELETE FROM `' . self::CATEGORY_TABLE . '` WHERE ' |
||||
. '`uid` = ? AND `type` = ? AND `category` = ?'); |
||||
$result = $stmt->execute(array($this->user, $this->type, $name)); |
||||
if (OC_DB::isError($result)) { |
||||
OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR); |
||||
} |
||||
} catch(Exception $e) { |
||||
OCP\Util::writeLog('core', __METHOD__ . ', exception: ' |
||||
. $e->getMessage(), OCP\Util::ERROR); |
||||
} |
||||
if(!is_null($id) && $id !== false) { |
||||
try { |
||||
$sql = 'DELETE FROM `' . self::RELATION_TABLE . '` ' |
||||
. 'WHERE `categoryid` = ?'; |
||||
$stmt = OCP\DB::prepare($sql); |
||||
$result = $stmt->execute(array($id)); |
||||
if (OC_DB::isError($result)) { |
||||
OC_Log::write('core', |
||||
__METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), |
||||
OC_Log::ERROR); |
||||
} |
||||
} catch(Exception $e) { |
||||
OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), |
||||
OCP\Util::ERROR); |
||||
return false; |
||||
} |
||||
} |
||||
} |
||||
OC_Log::write('core', __METHOD__.', after: ' |
||||
. print_r($this->categories, true), OC_Log::DEBUG); |
||||
if(!is_null($objects)) { |
||||
foreach($objects as $key=>&$value) { |
||||
$vobject = OC_VObject::parse($value[1]); |
||||
if(!is_null($vobject)) { |
||||
$object = null; |
||||
$componentname = ''; |
||||
if (isset($vobject->VEVENT)) { |
||||
$object = $vobject->VEVENT; |
||||
$componentname = 'VEVENT'; |
||||
} else |
||||
if (isset($vobject->VTODO)) { |
||||
$object = $vobject->VTODO; |
||||
$componentname = 'VTODO'; |
||||
} else |
||||
if (isset($vobject->VJOURNAL)) { |
||||
$object = $vobject->VJOURNAL; |
||||
$componentname = 'VJOURNAL'; |
||||
} else { |
||||
$object = $vobject; |
||||
} |
||||
$categories = $object->getAsArray('CATEGORIES'); |
||||
foreach($names as $name) { |
||||
$idx = $this->array_searchi($name, $categories); |
||||
if($idx !== false) { |
||||
OC_Log::write('core', __METHOD__ |
||||
.', unsetting: ' |
||||
. $categories[$this->array_searchi($name, $categories)], |
||||
OC_Log::DEBUG); |
||||
unset($categories[$this->array_searchi($name, $categories)]); |
||||
} |
||||
} |
||||
|
||||
$object->setString('CATEGORIES', implode(',', $categories)); |
||||
if($vobject !== $object) { |
||||
$vobject[$componentname] = $object; |
||||
} |
||||
$value[1] = $vobject->serialize(); |
||||
$objects[$key] = $value; |
||||
} else { |
||||
OC_Log::write('core', __METHOD__ |
||||
.', unable to parse. ID: ' . $value[0] . ', ' |
||||
. substr($value[1], 0, 50) . '(...)', OC_Log::DEBUG); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
// case-insensitive in_array |
||||
private function in_arrayi($needle, $haystack) { |
||||
if(!is_array($haystack)) { |
||||
return false; |
||||
} |
||||
return in_array(strtolower($needle), array_map('strtolower', $haystack)); |
||||
} |
||||
|
||||
// case-insensitive array_search |
||||
private function array_searchi($needle, $haystack) { |
||||
if(!is_array($haystack)) { |
||||
return false; |
||||
} |
||||
return array_search(strtolower($needle), array_map('strtolower', $haystack)); |
||||
} |
||||
} |
@ -0,0 +1,166 @@ |
||||
<?php |
||||
/** |
||||
* ownCloud |
||||
* |
||||
* @author Thomas Tanghus |
||||
* @copyright 2012-13 Thomas Tanghus (thomas@tanghus.net) |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
class Test_Tags extends PHPUnit_Framework_TestCase { |
||||
|
||||
protected $objectType; |
||||
protected $user; |
||||
protected $backupGlobals = FALSE; |
||||
|
||||
public function setUp() { |
||||
|
||||
OC_User::clearBackends(); |
||||
OC_User::useBackend('dummy'); |
||||
$this->user = uniqid('user_'); |
||||
$this->objectType = uniqid('type_'); |
||||
OC_User::createUser($this->user, 'pass'); |
||||
OC_User::setUserId($this->user); |
||||
$this->tagMgr = new OC\TagManager($this->user); |
||||
|
||||
} |
||||
|
||||
public function tearDown() { |
||||
//$query = OC_DB::prepare('DELETE FROM `*PREFIX*vcategories` WHERE `item_type` = ?'); |
||||
//$query->execute(array('test')); |
||||
} |
||||
|
||||
public function testInstantiateWithDefaults() { |
||||
$defaultTags = array('Friends', 'Family', 'Work', 'Other'); |
||||
|
||||
$tagger = $this->tagMgr->load($this->objectType, $defaultTags); |
||||
|
||||
$this->assertEquals(4, count($tagger->getTags())); |
||||
} |
||||
|
||||
public function testAddTags() { |
||||
$tags = array('Friends', 'Family', 'Work', 'Other'); |
||||
|
||||
$tagger = $this->tagMgr->load($this->objectType); |
||||
|
||||
foreach($tags as $tag) { |
||||
$result = $tagger->add($tag); |
||||
$this->assertGreaterThan(0, $result, 'add() returned an ID <= 0'); |
||||
$this->assertTrue((bool)$result); |
||||
} |
||||
|
||||
$this->assertFalse($tagger->add('Family')); |
||||
$this->assertFalse($tagger->add('fAMILY')); |
||||
|
||||
$this->assertCount(4, $tagger->getTags(), 'Wrong number of added tags'); |
||||
} |
||||
|
||||
public function testAddMultiple() { |
||||
$tags = array('Friends', 'Family', 'Work', 'Other'); |
||||
|
||||
$tagger = $this->tagMgr->load($this->objectType); |
||||
|
||||
foreach($tags as $tag) { |
||||
$this->assertFalse($tagger->hasTag($tag)); |
||||
} |
||||
|
||||
$result = $tagger->addMultiple($tags); |
||||
$this->assertTrue((bool)$result); |
||||
|
||||
foreach($tags as $tag) { |
||||
$this->assertTrue($tagger->hasTag($tag)); |
||||
} |
||||
|
||||
$this->assertCount(4, $tagger->getTags(), 'Not all tags added'); |
||||
} |
||||
|
||||
public function testIsEmpty() { |
||||
$tagger = $this->tagMgr->load($this->objectType); |
||||
|
||||
$this->assertEquals(0, count($tagger->getTags())); |
||||
$this->assertTrue($tagger->isEmpty()); |
||||
|
||||
$result = $tagger->add('Tag'); |
||||
$this->assertGreaterThan(0, $result, 'add() returned an ID <= 0'); |
||||
$this->assertNotEquals(false, $result, 'add() returned false'); |
||||
$this->assertFalse($tagger->isEmpty()); |
||||
} |
||||
|
||||
public function testdeleteTags() { |
||||
$defaultTags = array('Friends', 'Family', 'Work', 'Other'); |
||||
$tagger = $this->tagMgr->load($this->objectType, $defaultTags); |
||||
|
||||
$this->assertEquals(4, count($tagger->getTags())); |
||||
|
||||
$tagger->delete('family'); |
||||
$this->assertEquals(3, count($tagger->getTags())); |
||||
|
||||
$tagger->delete(array('Friends', 'Work', 'Other')); |
||||
$this->assertEquals(0, count($tagger->getTags())); |
||||
|
||||
} |
||||
|
||||
public function testRenameTag() { |
||||
$defaultTags = array('Friends', 'Family', 'Wrok', 'Other'); |
||||
$tagger = $this->tagMgr->load($this->objectType, $defaultTags); |
||||
|
||||
$this->assertTrue($tagger->rename('Wrok', 'Work')); |
||||
$this->assertTrue($tagger->hasTag('Work')); |
||||
$this->assertFalse($tagger->hastag('Wrok')); |
||||
$this->assertFalse($tagger->rename('Wrok', 'Work')); |
||||
|
||||
} |
||||
|
||||
public function testTagAs() { |
||||
$objids = array(1, 2, 3, 4, 5, 6, 7, 8, 9); |
||||
|
||||
$tagger = $this->tagMgr->load($this->objectType); |
||||
|
||||
foreach($objids as $id) { |
||||
$tagger->tagAs($id, 'Family'); |
||||
} |
||||
|
||||
$this->assertEquals(1, count($tagger->getTags())); |
||||
$this->assertEquals(9, count($tagger->getIdsForTag('Family'))); |
||||
} |
||||
|
||||
/** |
||||
* @depends testTagAs |
||||
*/ |
||||
public function testUnTag() { |
||||
$objIds = array(1, 2, 3, 4, 5, 6, 7, 8, 9); |
||||
|
||||
// Is this "legal"? |
||||
$this->testTagAs(); |
||||
$tagger = $this->tagMgr->load($this->objectType); |
||||
|
||||
foreach($objIds as $id) { |
||||
$this->assertTrue(in_array($id, $tagger->getIdsForTag('Family'))); |
||||
$tagger->unTag($id, 'Family'); |
||||
$this->assertFalse(in_array($id, $tagger->getIdsForTag('Family'))); |
||||
} |
||||
|
||||
$this->assertEquals(1, count($tagger->getTags())); |
||||
$this->assertEquals(0, count($tagger->getIdsForTag('Family'))); |
||||
} |
||||
|
||||
public function testFavorite() { |
||||
$tagger = $this->tagMgr->load($this->objectType); |
||||
$this->assertTrue($tagger->addToFavorites(1)); |
||||
$this->assertTrue($tagger->removeFromFavorites(1)); |
||||
} |
||||
|
||||
} |
@ -1,128 +0,0 @@ |
||||
<?php |
||||
/** |
||||
* ownCloud |
||||
* |
||||
* @author Thomas Tanghus |
||||
* @copyright 2012 Thomas Tanghus (thomas@tanghus.net) |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
//require_once("../lib/template.php"); |
||||
|
||||
class Test_VCategories extends PHPUnit_Framework_TestCase { |
||||
|
||||
protected $objectType; |
||||
protected $user; |
||||
protected $backupGlobals = FALSE; |
||||
|
||||
public function setUp() { |
||||
|
||||
OC_User::clearBackends(); |
||||
OC_User::useBackend('dummy'); |
||||
$this->user = uniqid('user_'); |
||||
$this->objectType = uniqid('type_'); |
||||
OC_User::createUser($this->user, 'pass'); |
||||
OC_User::setUserId($this->user); |
||||
|
||||
} |
||||
|
||||
public function tearDown() { |
||||
//$query = OC_DB::prepare('DELETE FROM `*PREFIX*vcategories` WHERE `item_type` = ?'); |
||||
//$query->execute(array('test')); |
||||
} |
||||
|
||||
public function testInstantiateWithDefaults() { |
||||
$defcategories = array('Friends', 'Family', 'Work', 'Other'); |
||||
|
||||
$catmgr = new OC_VCategories($this->objectType, $this->user, $defcategories); |
||||
|
||||
$this->assertEquals(4, count($catmgr->categories())); |
||||
} |
||||
|
||||
public function testAddCategories() { |
||||
$categories = array('Friends', 'Family', 'Work', 'Other'); |
||||
|
||||
$catmgr = new OC_VCategories($this->objectType, $this->user); |
||||
|
||||
foreach($categories as $category) { |
||||
$result = $catmgr->add($category); |
||||
$this->assertTrue((bool)$result); |
||||
} |
||||
|
||||
$this->assertFalse($catmgr->add('Family')); |
||||
$this->assertFalse($catmgr->add('fAMILY')); |
||||
|
||||
$this->assertEquals(4, count($catmgr->categories())); |
||||
} |
||||
|
||||
public function testdeleteCategories() { |
||||
$defcategories = array('Friends', 'Family', 'Work', 'Other'); |
||||
$catmgr = new OC_VCategories($this->objectType, $this->user, $defcategories); |
||||
$this->assertEquals(4, count($catmgr->categories())); |
||||
|
||||
$catmgr->delete('family'); |
||||
$this->assertEquals(3, count($catmgr->categories())); |
||||
|
||||
$catmgr->delete(array('Friends', 'Work', 'Other')); |
||||
$this->assertEquals(0, count($catmgr->categories())); |
||||
|
||||
} |
||||
|
||||
public function testrenameCategory() { |
||||
$defcategories = array('Friends', 'Family', 'Wrok', 'Other'); |
||||
$catmgr = new OC_VCategories($this->objectType, $this->user, $defcategories); |
||||
|
||||
$this->assertTrue($catmgr->rename('Wrok', 'Work')); |
||||
$this->assertTrue($catmgr->hasCategory('Work')); |
||||
$this->assertFalse($catmgr->hasCategory('Wrok')); |
||||
$this->assertFalse($catmgr->rename('Wrok', 'Work')); |
||||
|
||||
} |
||||
|
||||
public function testAddToCategory() { |
||||
$objids = array(1, 2, 3, 4, 5, 6, 7, 8, 9); |
||||
|
||||
$catmgr = new OC_VCategories($this->objectType, $this->user); |
||||
|
||||
foreach($objids as $id) { |
||||
$catmgr->addToCategory($id, 'Family'); |
||||
} |
||||
|
||||
$this->assertEquals(1, count($catmgr->categories())); |
||||
$this->assertEquals(9, count($catmgr->idsForCategory('Family'))); |
||||
} |
||||
|
||||
/** |
||||
* @depends testAddToCategory |
||||
*/ |
||||
public function testRemoveFromCategory() { |
||||
$objids = array(1, 2, 3, 4, 5, 6, 7, 8, 9); |
||||
|
||||
// Is this "legal"? |
||||
$this->testAddToCategory(); |
||||
$catmgr = new OC_VCategories($this->objectType, $this->user); |
||||
|
||||
foreach($objids as $id) { |
||||
$this->assertTrue(in_array($id, $catmgr->idsForCategory('Family'))); |
||||
$catmgr->removeFromCategory($id, 'Family'); |
||||
$this->assertFalse(in_array($id, $catmgr->idsForCategory('Family'))); |
||||
} |
||||
|
||||
$this->assertEquals(1, count($catmgr->categories())); |
||||
$this->assertEquals(0, count($catmgr->idsForCategory('Family'))); |
||||
} |
||||
|
||||
} |
Loading…
Reference in new issue