You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

386 lines
11 KiB

<?php
// (c) Copyright by authors of the Tiki Wiki CMS Groupware Project
//
// All Rights Reserved. See copyright.txt for details and a complete list of authors.
// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details.
// $Id$
/**
* RelationLib
*
* @uses TikiDb_Bridge
*/
class RelationLib extends TikiDb_Bridge
{
private $table;
public function __construct()
{
$this->table = $this->table('tiki_object_relations');
}
/**
* Obtains the list of relations with a given object as the source.
* Optionally, the relation searched for can be specified. If the
* relation ends with a dot, it will be used as a wildcard.
*/
public function get_relations_from($type, $object, $relation = '', $orderBy = '', $max = -1)
{
if (substr($relation, -7) === '.invert') {
return $this->get_relations_to($type, $object, substr($relation, 0, -7), $orderBy, $max);
}
$cond = [
'source_type' => $type,
'source_itemId' => $object
];
$fields = [
'relationId',
'relation',
'type' => 'target_type',
'itemId' => 'target_itemId',
];
$cond = $this->apply_relation_condition($relation, $cond);
return $this->table->fetchAll($fields, $cond, $max, -1, $orderBy);
}
/**
* Obtain a list of objects that have a given relation
*
*/
public function get_related_objects($relation, $orderBy = '', $max = -1)
{
$cond = [
'relation' => $relation,
];
$fields = [
'source_type',
'source_itemId',
'target_type',
'target_itemId',
];
return $this->table->fetchAll($fields, $cond, $max, -1, $orderBy); /// resultset as an array
}
/**
* This is a convenience function to get all the matching IDs from
* get_relations_from without caring about the object type which might be assumed
*/
public function get_object_ids_with_relations_from($type, $object, $relation = null)
{
$ret = [];
$relations = $this->get_relations_from($type, $object, $relation);
foreach ($relations as $r) {
$ret[] = $r['itemId'];
}
return $ret;
}
/**
* This is a convenience function to get all the matching IDs from
* get_relations_to without caring about the object type which might be assumed
*/
public function get_object_ids_with_relations_to($type, $object, $relation = null)
{
$ret = [];
$relations = $this->get_relations_to($type, $object, $relation);
foreach ($relations as $r) {
$ret[] = $r['itemId'];
}
return $ret;
}
/**
* @param $type
* @param $object
* @param $relation
* @return mixed
*/
public function get_relations_to($type, $object, $relation = '', $orderBy = '', $max = -1)
{
if (substr($relation, -7) === '.invert') {
return $this->get_relations_from($type, $object, substr($relation, 0, -7), $orderBy, $max);
}
$cond = [
'target_type' => $type,
'target_itemId' => $object
];
$fields = [
'relationId',
'relation',
'type' => 'source_type',
'itemId' => 'source_itemId',
];
$cond = $this->apply_relation_condition($relation, $cond);
return $this->table->fetchAll($fields, $cond, $max, -1, $orderBy);
}
/**
* The relation must contain at least two dots and only lowercase letters.
* NAMESPACE management and relation naming.
* Please see http://dev.tiki.org/Object+Attributes+and+Relations for guidelines on
* relation naming, and document new tiki.*.* names that you add.
* (also grep "add_relation" just in case there are undocumented names already used)
*/
public function add_relation($relation, $src_type, $src_object, $target_type, $target_object, $ignoreExisting = false)
{
$relation = TikiFilter::get('attribute_type')->filter($relation);
if (substr($relation, -7) === '.invert') {
return $this->add_relation(substr($relation, 0, -7), $target_type, $target_object, $src_type, $src_object);
}
if ($relation) {
if (! $id = $this->get_relation_id($relation, $src_type, $src_object, $target_type, $target_object)) {
$id = $this->table->insert(
[
'relation' => $relation,
'source_type' => $src_type,
'source_itemId' => $src_object,
'target_type' => $target_type,
'target_itemId' => $target_object,
]
);
} elseif ($ignoreExisting) {
return 0;
}
// Array written to match event trigger that was previously in wikiplugin_addrelation
TikiLib::events()->trigger('tiki.social.relation.add', [
'relation' => $relation,
'sourcetype' => $src_type,
'sourceobject' => $src_object,
'type' => $target_type,
'object' => $target_object,
'user' => $GLOBALS['user'],
]);
TikiLib::lib('tiki')->refresh_index($src_type, $src_object);
TikiLib::lib('tiki')->refresh_index($target_type, $target_object);
return $id;
} else {
return 0;
}
}
/**
* @param $relation
* @param $src_type
* @param $src_object
* @param $target_type
* @param $target_object
* @return int
*/
public function get_relation_id($relation, $src_type, $src_object, $target_type, $target_object)
{
$relation = TikiFilter::get('attribute_type')->filter($relation);
if (substr($relation, -7) === '.invert') {
return $this->get_relation_id(substr($relation, 0, -7), $target_type, $target_object, $src_type, $src_object);
}
$id = 0;
if ($relation) {
$id = $this->table->fetchOne(
'relationId',
[
'relation' => $relation,
'source_type' => $src_type,
'source_itemId' => $src_object,
'target_type' => $target_type,
'target_itemId' => $target_object,
]
);
}
return $id;
}
/**
* @param $relation_prefix
* @param $src_type
* @param $src_object
* @param $target_type
* @param $target_object
* @return array
*/
public function get_relations_by_prefix($relation_prefix, $src_type, $src_object, $target_type, $target_object)
{
$ids = [];
if ($relation_prefix) {
$ids = $this->table->fetchAll(
[],
[
'relation' => $this->table->like($relation_prefix . ".%"),
'source_type' => $src_type,
'source_itemId' => $src_object,
'target_type' => $target_type,
'target_itemId' => $target_object,
]
);
}
return $ids;
}
/**
* @param $relation
* @param $type
* @param $object
* @param $get_invert default=false
* @return int
*/
public function get_relation_count($relation, $type, $object = null, $get_invert = false)
{
$relation = TikiFilter::get('attribute_type')->filter($relation);
if (! $relation) {
return 0;
}
if ($get_invert) {
$count = $this->table->fetchCount(
array_filter([
'relation' => $relation,
'source_type' => $type,
'source_itemId' => $object,
])
);
} else {
$count = $this->table->fetchCount(
array_filter([
'relation' => $relation,
'target_type' => $type,
'target_itemId' => $object,
])
);
}
return $count;
}
public function relation_exists($relation, $type)
{
return $this->get_relation_count($relation, $type) || $this->get_relation_count($relation, $type, null, true);
}
/**
* @param $id
* @return mixed
*/
function get_relation($id)
{
return $this->table->fetchFullRow(
[
'relationId' => $id,
]
);
}
/**
* @param $id
*/
public function remove_relation($id)
{
$relation_info = $this->get_relation($id);
$this->table->delete(
[
'relationId' => $id,
]
);
$this->table('tiki_object_attributes')->deleteMultiple(
[
'type' => 'relation',
'itemId' => $id,
]
);
TikiLib::events()->trigger('tiki.social.relation.remove', [
'relation' => $relation_info['relation'],
'sourcetype' => $relation_info['source_type'],
'sourceobject' => $relation_info['source_itemId'],
'type' => $relation_info['target_type'],
'object' => $relation_info['target_itemId'],
'user' => $GLOBALS['user'],
]);
TikiLib::lib('tiki')->refresh_index($relation_info['source_type'], $relation_info['source_itemId']);
TikiLib::lib('tiki')->refresh_index($relation_info['target_type'], $relation_info['target_itemId']);
}
/**
* Remove all relations from that type and source items belonging to that tracker
* @param $relation - the relation type
* @param $trackerId - the tracker id
*/
public function remove_relation_type($relation, $trackerId)
{
return $this->query("DELETE FROM tiki_object_relations
WHERE relation = ?
AND source_type = 'trackeritem'
AND source_itemId IN(
SELECT itemId FROM tiki_tracker_items WHERE trackerId = ?
)", [$relation, $trackerId]);
}
/**
* Remove all relations of a type for single object
* @param $fromType - object type
* @param $fromId - object itemId
* @param $relationType - relation type originating from that object
*/
public function remove_relations_from($fromType, $fromId, $relationType)
{
return $this->table->deleteMultiple(
[
'relation' => $relationType,
'source_type' => $fromType,
'source_itemId' => $fromId
]
);
}
/**
* Changes to relation name should update existing relation table entries
*
* @param $from - old relation name
* @param $to - new relation name
*/
public function update_relation($from, $to)
{
$this->table->updateMultiple([
'relation' => $to
], [
'relation' => $from
]);
}
/**
* @param $relation
* @param $cond
* @param $vars
*/
private function apply_relation_condition($relation, $cond)
{
$relation = TikiFilter::get('attribute_type')->filter($relation);
if ($relation) {
if (substr($relation, -1) == '.') {
$relation .= '%';
}
$cond['relation'] = $this->table->like($relation);
}
return $cond;
}
}