get_object_id($type, $itemId); if ($objectId) { if (! empty($description) || ! empty($name) || ! empty($href)) { $query = "update `tiki_objects` set `description`=?,`name`=?,`href`=? where `objectId`=?"; $this->query($query, [$description, $name, $href, $objectId]); } } else { if (is_null($description)) { switch ($type) { case 'article': $artlib = TikiLib::lib('art'); $info = $artlib->get_article($itemId); $description = $info['heading']; $name = $info['title']; $href = 'tiki-read_article.php?articleId=' . $itemId; break; case 'blog': $bloglib = TikiLib::lib('blog'); $info = $bloglib->get_blog($itemId); $description = $info['description']; $name = $info['title']; $href = 'tiki-view_blog.php?blogId=' . $itemId; break; case 'calendar': $calendarlib = TikiLib::lib('calendar'); $info = $calendarlib->get_calendar($itemId); $description = $info['description']; $name = $info['name']; $href = 'tiki-calendar.php?calId=' . $itemId; break; case 'directory': $info = $this->get_directory($itemId); $description = $info['description']; $name = $info['name']; $href = 'tiki-directory_browse.php?parent=' . $itemId; break; case 'faq': $info = TikiLib::lib('faq')->get_faq($itemId); $description = $info['description']; $name = $info['title']; $href = 'tiki-view_faq.php?faqId=' . $itemId; break; case 'file': $filegallib = TikiLib::lib('filegal'); $info = $filegallib->get_file_info($itemId, false, false, false); $description = $info['description']; $name = $info['name']; $href = 'tiki-upload_file.php?fileId=' . $itemId; break; case 'file gallery': $filegallib = TikiLib::lib('filegal'); $info = $filegallib->get_file_gallery($itemId); $description = $info['description']; $name = $info['name']; $href = 'tiki-list_file_gallery.php?galleryId=' . $itemId; break; case 'forum': $commentslib = TikiLib::lib('comments'); $info = $commentslib->get_forum($itemId); $description = $info['description']; $name = $info['name']; $href = 'tiki-view_forum.php?forumId=' . $itemId; break; case 'perspective': $info = TikiLib::lib('perspective')->get_perspective($itemId); $name = $info['name']; $href = 'tiki-switch_perspective.php?perspective=' . $itemId; break; case 'poll': $polllib = TikiLib::lib('poll'); $info = $polllib->get_poll($itemId); $description = $info['title']; $name = $info['title']; $href = 'tiki-poll_form.php?pollId=' . $itemId; break; case 'quiz': $info = TikiLib::lib('quiz')->get_quiz($itemId); $description = $info['description']; $name = $info['name']; $href = 'tiki-take_quiz.php?quizId=' . $itemId; break; case 'tracker': $trklib = TikiLib::lib('trk'); $info = $trklib->get_tracker($itemId); $description = $info['description']; $name = $info['name']; $href = 'tiki-view_tracker.php?trackerId=' . $itemId; break; case 'trackeritem': $trklib = TikiLib::lib('trk'); $info = $trklib->get_tracker_item($itemId); $description = ''; $name = $trklib->get_isMain_value($info['trackerId'], $itemId); $href = "tiki-view_tracker_item.php?itemId=$itemId&trackerId=" . $info['trackerId']; break; case 'wiki page': if (! ($info = $this->get_page_info($itemId))) { return; } $description = $info["description"]; $name = $itemId; $href = 'tiki-index.php?page=' . urlencode($itemId); break; case 'template': $info = TikiLib::lib('template')->get_template($itemId); $description = ''; $name = $info['name']; $href = "tiki-admin_content_templates.php?templateId=$itemId"; break; default: if ($checkHandled) { return false; } else { $description = ''; $name = ''; $href = ''; } } } $objectId = $this->insert_object($type, $itemId, $description, $name, $href); } return $objectId; } /** * Returns an array of object types supported (and therefore can be categorised etc) * * @return array */ public static function get_supported_types() { return [ 'article', 'blog', 'calendar', 'directory', 'faq', 'file', 'file gallery', 'forum', 'image gallery', 'perspective', 'poll', 'quiz', 'tracker', 'trackeritem', 'wiki page', 'template', ]; } public function getSelectorType($type) { $supported = [ 'category' => 'category', 'file_gallery' => 'file gallery', 'forum' => 'forum', 'group' => 'group', 'tracker' => 'tracker', 'tracker_field' => 'trackerfield', 'trackerfield' => 'trackerfield', 'wiki_page' => 'wiki page', 'wiki page' => 'wiki page', 'template' => 'template', ]; if (isset($supported[$type])) { return $supported[$type]; } else { return false; } } public function insert_object($type, $itemId, $description = '', $name = '', $href = '') { if (! $itemId) { // When called with a blank page name or any other empty value, no insertion should be made return false; } $tikilib = TikiLib::lib('tiki'); $table = $this->table('tiki_objects'); return $table->insert( [ 'type' => $type, 'itemId' => (string) $itemId, 'description' => $description, 'name' => $name, 'href' => $href, 'created' => (int) $tikilib->now, 'hits' => 0, 'comments_locked' => 'n', ] ); } public function get_object_id($type, $itemId) { $query = "select `objectId` from `tiki_objects` where `type`=? and `itemId`=?"; return $this->getOne($query, [$type, $itemId]); } // Returns an array containing the object ids of objects of the same type. // Each entry uses the item id as key and the object id as key. Items with no object id are ignored. public function get_object_ids($type, $itemIds) { if (empty($itemIds)) { return []; } $query = 'select `objectId`, `itemId` from `tiki_objects` where `type`=? and `itemId` IN (' . implode(',', array_fill(0, count($itemIds), '?')) . ')'; $result = $this->query($query, array_merge([$type], $itemIds)); $objectIds = []; while ($res = $result->fetchRow()) { $objectIds[$res['itemId']] = $res['objectId']; } return $objectIds; } public function get_needed_perm($objectType, $action) { switch ($objectType) { case 'wiki page': // no return case 'wiki': switch ($action) { case 'view': // no return case 'read': return 'tiki_p_view'; case 'edit': return 'tiki_p_edit'; } // no return case 'article': switch ($action) { case 'view': case 'read': return 'tiki_p_read_article'; case 'edit': return 'tiki_p_edit_article'; } // no return case 'post': switch ($action) { case 'view': case 'read': return 'tiki_p_read_blog'; case 'edit': return 'tiki_p_create_blog'; } // no return case 'blog': switch ($action) { case 'view': case 'read': return 'tiki_p_read_blog'; case 'edit': return 'tiki_p_create_blog'; } // no return case 'faq': switch ($action) { case 'view': case 'read': return 'tiki_p_view_faqs'; case 'edit': return 'tiki_p_admin_faqs'; } // no return case 'file gallery': switch ($action) { case 'view': case 'read': return 'tiki_p_view_file_gallery'; case 'edit': return 'tiki-admin_file_galleries'; } // no return case 'poll': switch ($action) { case 'view': case 'read': return 'tiki_p_vote_poll'; case 'edit': return 'tiki_p_admin'; } // no return case 'comment': case 'comments': switch ($action) { case 'view': case 'read': return 'tiki_p_read_comments'; case 'edit': return 'tiki_p_edit_comments'; } // no return case 'trackeritem': switch ($action) { case 'view': case 'read': return 'tiki_p_view_trackers'; case 'edit': return 'tiki_p_modify_tracker_items'; } // no return case 'trackeritem_closed': switch ($action) { case 'view': case 'read': return 'tiki_p_view_trackers'; case 'edit': return 'tiki_p_modify_tracker_items_closed'; } // no return case 'trackeritem_pending': switch ($action) { case 'view': case 'read': return 'tiki_p_view_trackers'; case 'edit': return 'tiki_p_modify_tracker_items_pending'; } // no return case 'tracker': switch ($action) { case 'view': case 'read': return 'tiki_p_list_trackers'; case 'edit': return 'tiki_p_admin_trackers'; } // no return case 'template': switch ($action) { case 'view': case 'read': return 'tiki_p_use_content_templates'; case 'edit': return 'tiki_p_edit_content_templates'; } // no return default: return ''; } } public function get_info($objectType, $object) { switch ($objectType) { case 'wiki': case 'wiki page': $tikilib = TikiLib::lib('tiki'); $info = $tikilib->get_page_info($object); return ['title' => $object, 'data' => $info['data'], 'is_html' => $info['is_html']]; case 'article': $artlib = TikiLib::lib('art'); $info = $artlib->get_article($object); return ['title' => $info['title'], 'data' => $info['body']]; case 'file gallery': $info = TikiLib::lib('filegal')->get_file_gallery_info($object); return ['title' => $info['name']]; case 'blog': $info = TikiLib::lib('blog')->get_blog($object); return ['title' => $info['title']]; case 'post': case 'blog post': case 'blogpost': $info = TikiLib::lib('blog')->get_post($object); return ['title' => $info['title']]; case 'forum': $info = TikiLib::lib('comments')->get_forum($object); return ['title' => $info['name']]; case 'forum post': $info = TikiLib::lib('comments')->get_comment($object); return ['title' => $info['title']]; case 'tracker': $info = TikiLib::lib('trk')->get_tracker($object); return ['title' => $info['name']]; case 'trackerfield': $info = TikiLib::lib('trk')->get_tracker_field($object); return ['title' => $info['name']]; case 'goal': return TikiLib::lib('goal')->fetchGoal($object); case 'template': $info = TikiLib::lib('template')->get_template($object); return ['title' => $info['name']]; } return (['error' => 'true']); } public function set_data($objectType, $object, $data) { switch ($objectType) { case 'wiki': case 'wiki page': global $user; $tikilib = TikiLib::lib('tiki'); $tikilib->update_page($object, $data, tra('section edit'), $user, $tikilib->get_ip_address()); break; } } public function delete_object($type, $itemId) { $query = 'delete from `tiki_objects` where `itemId`=? and `type`=?'; $this->query($query, [$itemId, $type]); } public function delete_object_via_objectid($objectId) { $query = 'delete from `tiki_objects` where `objectId`=?'; $this->query($query, [(int) $objectId]); } public function get_object($type, $itemId) { $query = 'select * from `tiki_objects` where `itemId`=? and `type`=?'; $result = $this->query($query, [$itemId, $type]); return $result->fetchRow(); } public function get_object_via_objectid($objectId) { $query = 'select * from `tiki_objects` where `objectId`=?'; $result = $this->query($query, [(int) $objectId]); return $result->fetchRow(); } /** * @param string $type * @param string $id * @param string|null $format - trackeritem format coming from ItemLink field or null by default * * @return void|string * @throws Exception */ public function get_title($type, string $id, ?string $format = null) { $detail = ''; switch ($type) { case 'trackeritemfield': $type = 'trackeritem'; $ids = explode(':', $id); $id = (int)$ids[0]; $fieldId = (int)$ids[1]; $trackerlib = TikiLib::lib('trk'); $info = $trackerlib->get_field_info($fieldId); $extra = $info['name']; // no return case 'trackeritem': $defaultTitle = TikiLib::lib('trk')->get_isMain_value(null, $id); $extra = $extra ?? ''; return $this->getFormattedTitle($type, $id, $defaultTitle, $format, $extra); case 'category': return TikiLib::lib('categ')->get_category_name($id); case 'file': return TikiLib::lib('filegal')->get_file_label($id); case 'topic': $meta = TikiLib::lib('art')->get_topic($id); return $meta['name']; case 'group': return $id; case 'user': if (is_int($id)) { $id = TikiLib::lib('tiki')->get_user_login($id); } return TikiLib::lib('user')->clean_user($id); case 'calendar': $info = TikiLib::lib('calendar')->get_calendar($id); return $info['name']; case 'calendar event': case 'calendaritem': $info = TikiLib::lib('calendar')->get_item($id); return $this->getFormattedTitle($type, $id, $info['name'], $format); } $title = $this->table('tiki_objects')->fetchOne( 'name', [ 'type' => $type, 'itemId' => $id, ] ); if ($title) { return $title; } $info = $this->get_info($type, $id); if (isset($info['title'])) { return $info['title']; } if (isset($info['name'])) { return $info['name']; } } /** * @param string $type * @param string $id usually an int but strings for wiki pages * @param string|null $defaultTitle * @param string|null $format * * @param string|null $extra * * @return string * @throws Exception */ public function getFormattedTitle(string $type, string $id, ?string $defaultTitle, ?string $format = '', ?string $extra = ''): string { if ($format) { $lib = TikiLib::lib('unifiedsearch'); $query = $lib->buildQuery([ 'object_type' => $type, 'object_id' => $id ]); $result = $query->search($lib->getIndex()); $result->applyTransform(function ($item) use ($format) { return preg_replace_callback('/\{(\w+)\}/', function ($matches) use ($item, $format) { $key = $matches[1]; if (isset($item[$key])) { return $item[$key]; } elseif (! $format || $format == '{title}') { return tr('empty'); } else { return ''; } }, $format); }); $titles = $result->getArrayCopy(); $title = array_shift($titles); } else { $title = $defaultTitle; } if (empty($title)) { $title = "$type:$id"; } if (isset($extra) && $extra) { $title .= ' (' . $extra . ')'; } return $title; } /** * Gets a wiki parsed content for an object. This is used in case an object can have wiki parsed * content that generates relations (ex: Plugin Include). * * This content can be used to find elements, but displaying to user might not be a good idea, since * text from different fields can be concatenated. * * @param string $type * @param $id * @return void|string */ public function get_wiki_content($type, $objectId) { if (substr($type, -7) == 'comment') { $comment_info = TikiLib::lib('comments')->get_comment((int)$objectId); return $comment_info['data']; } switch ($type) { case 'wiki': $type = 'wiki page'; // no return case 'wiki page': $info = $this->get_page_info($objectId); return $info['data']; case 'forum post': $comment_info = TikiLib::lib('comments')->get_comment((int)$objectId); return $comment_info['data']; case 'article': $info = TikiLib::lib('art')->get_article((int)$objectId); return $info['heading'] . "\n" . $info['body']; case 'tracker': $tracker_info = TikiLib::lib('trk')->get_tracker((int)$objectId); return $tracker_info['description']; case 'trackerfield': $field_info = TikiLib::lib('trk')->get_field_info((int)$objectId); return $field_info['description']; case 'trackeritemfield': $objectId = explode(':', $objectId); $itemId = (int)$objectId[0]; $fieldId = (int)$objectId[1]; $trackerlib = TikiLib::lib('trk'); $item_info = $trackerlib->get_tracker_item($itemId); return $item_info[$fieldId]; } } /** * @param string $type * @return string */ public function get_verbose_type($type) { if (substr($type, -7) == 'comment') { $isComment = true; $type = substr($type, 0, strlen($type) - 8); } else { $isComment = false; } switch ($type) { case 'trackeritem': $type = 'tracker item'; break; case 'trackeritemfield': $type = 'tracker item field'; break; case 'trackerfield': $type = 'tracker field'; break; case 'wiki': $type = 'wiki page'; break; } if ($isComment) { $type .= " comment"; } return tra(ucwords($type)); } /** * Returns a hash indicating which permission is needed for viewing an object of desired type. * * @param boolean $comment - indicate if returned permission must be comment-related, e.g. * am I allowed to see comments on a tracker item if I have or don't have tiki_p_tracker_view_comments. * This allows search index to properly update comment permissions not basing them on viewing * parent tracker item or wiki page but the comment itself. */ public static function map_object_type_to_permission($comment = false) { return [ 'wiki page' => $comment ? 'tiki_p_wiki_view_comments' : 'tiki_p_view', 'wiki' => $comment ? 'tiki_p_wiki_view_comments' : 'tiki_p_view', 'forum' => 'tiki_p_forum_read', 'forum post' => 'tiki_p_forum_read', 'file gallery' => 'tiki_p_view_file_gallery', 'tracker' => 'tiki_p_view_trackers', 'blog' => 'tiki_p_read_blog', 'quiz' => 'tiki_p_take_quiz', 'template' => 'tiki_p_use_content_templates', // overhead - we are checking individual permission on types below, but they // can't have individual permissions, although they can be categorized. // should they have permissions too? 'poll' => 'tiki_p_vote_poll', 'survey' => 'tiki_p_take_survey', 'directory' => 'tiki_p_view_directory', 'faq' => 'tiki_p_view_faqs', 'sheet' => 'tiki_p_view_sheet', // these ones are tricky, because permission type is for container, not object itself. // I think we need to refactor permission schemes for them to be wysiwyca - lfagundes // // by now they're not showing, list_category_objects needs support for ignoring permissions // for a type. 'blog post' => 'tiki_p_read_blog', 'article' => 'tiki_p_read_article', 'submission' => 'tiki_p_approve_submission', 'calendar' => 'tiki_p_view_calendar', 'file' => 'tiki_p_download_files', 'trackeritem' => $comment ? 'tiki_p_tracker_view_comments' : 'tiki_p_view_trackers', // newsletters can't be categorized, although there's some code in tiki-admin_newsletters.php // 'newsletter' => ?, // 'events' => ?, ]; } public function get_metadata($type, $object, &$classList) { $smarty = TikiLib::lib('smarty'); $smarty->loadPlugin('smarty_modifier_escape'); $escapedType = smarty_modifier_escape($type); $escapedObject = smarty_modifier_escape($object); $metadata = ' data-type="' . $escapedType . '" data-object="' . $escapedObject . '"'; if ($coordinates = TikiLib::lib('geo')->get_coordinates($type, $object)) { $classList[] = 'geolocated'; $metadata .= " data-geo-lat=\"{$coordinates['lat']}\" data-geo-lon=\"{$coordinates['lon']}\""; if (isset($coordinates['zoom'])) { $metadata .= " data-geo-zoom=\"{$coordinates['zoom']}\""; } } $attributelib = TikiLib::lib('attribute'); $attributes = $attributelib->get_attributes($type, $object); if (isset($attributes['tiki.icon.src'])) { $escapedIcon = smarty_modifier_escape($attributes['tiki.icon.src']); $metadata .= " data-icon-src=\"$escapedIcon\""; } return $metadata; } public function get_typeItemsInfo($type) // Returns information on all items of an object type (eg: menu, article, etc) from tiki_objects table { //get objects $queryObjectInfo = 'select * from `tiki_objects` where `type`=?'; $resultObjectInfo = $this->fetchAll($queryObjectInfo, [$type]); //get object attributes foreach ($resultObjectInfo as &$tempInfo) { $objectAttributes = TikiLib::lib('attribute')->get_attributes($tempInfo['type'], $tempInfo['objectId']); $tempInfo = array_merge($tempInfo, $objectAttributes); } unset($tempInfo); //return information return $resultObjectInfo; } public function get_maintainers() // get all objects that have maintainers ??? GET_MAINTAINED_OBJECTS { $relationlib = TikiLib::lib('relation'); return $relationlib->get_related_objects('tiki.object.maintainer'); } public function set_maintainers($objectId, array $maintainers, $type = 'wiki page') { $relationlib = TikiLib::lib('relation'); foreach ($maintainers as $maintainer) { $relationlib->add_relation('tiki.object.maintainer', $type, $objectId, 'user', $maintainer); } } public function get_freshness($objectId, $type = 'wiki page') { if ($type === 'wiki page') { $info = TikiLib::lib('tiki')->get_page_info($objectId, false); if (isset($info)) { $lastModif = $info['lastModif']; $freshness = (int) ((time() - $lastModif) / self::SECONDSPERDAY); return $freshness; } } else { Feedback::error(tr('Object freshness not supported yet for object type %0', $type)); } return false; } }