1<?php
2// (c) Copyright by authors of the Tiki Wiki CMS Groupware Project
3//
4// All Rights Reserved. See copyright.txt for details and a complete list of authors.
5// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details.
6// $Id$
7
8class Tracker_Field_Articles extends Tracker_Field_Abstract
9{
10	private $articleSource;
11
12	public static function getTypes()
13	{
14		$db = TikiDb::get();
15		$topics = $db->table('tiki_topics')->fetchMap('topicId', 'name', [], -1, -1, 'name_asc');
16		$types = $db->table('tiki_article_types')->fetchColumn('type', []);
17		$types = array_combine($types, $types);
18
19		$options = [
20			'articles' => [
21				'name' => tr('Articles'),
22				'description' => tr('Attach articles to the tracker item.'),
23				'prefs' => ['trackerfield_articles', 'feature_articles'],
24				'tags' => ['advanced'],
25				'help' => 'Articles Tracker Field',
26				'default' => 'n',
27				'params' => [
28					'topicId' => [
29						'name' => tr('Topic'),
30						'description' => tr('Default article topic'),
31						'filter' => 'int',
32						'profile_reference' => 'article_topic',
33						'options' => $topics,
34					],
35					'type' => [
36						'name' => tr('Article Type'),
37						'description' => tr('Default article type'),
38						'filter' => 'text',
39						'profile_reference' => 'article_type',
40						'options' => $types,
41					],
42				],
43			],
44		];
45		return $options;
46	}
47
48	function getFieldData(array $requestData = [])
49	{
50		global $prefs;
51		$ins_id = $this->getInsertId();
52		if (isset($requestData[$ins_id])) {
53			if (is_string($requestData[$ins_id])) {
54				$articleIds = explode(',', $requestData[$ins_id]);
55			} else {
56				$articleIds = $requestData[$ins_id];
57			}
58
59			$articleIds = array_filter(array_map('intval', $articleIds));
60			$value = implode(',', $articleIds);
61		} else {
62			$value = $this->getValue();
63
64			// Obtain the information from the database for display
65			$articleIds = array_filter(explode(',', $value));
66		}
67
68		return [
69			'value' => $value,
70			'articleIds' => $articleIds,
71		];
72	}
73
74	function addValue($articleId) {
75		$existing = explode(',', $this->getValue());
76		if (! in_array($articleId, $existing)) {
77			$existing[] = $articleId;
78		}
79		return implode(',', $existing);
80	}
81
82	function removeValue($articleId) {
83		$existing = explode(',', $this->getValue());
84		$existing = array_filter($existing, function($v) use ($articleId) {
85			return $v != $articleId;
86		});
87		return implode(',', $existing);
88	}
89
90	function renderInput($context = [])
91	{
92		global $prefs;
93		// if the article is being indexed with the trackeritem as part of the autogenerated rss feature, the field should become read-only
94		if ($prefs['tracker_article_indexing'] == 'y' && $prefs['tracker_article_trackerId'] == $this->getConfiguration('trackerId')) {
95			$readonly = true;
96		} else {
97			$readonly = false;
98		}
99		$articleIds = $this->getConfiguration('articleIds');
100
101		return $this->renderTemplate('trackerinput/articles.tpl', $context, [
102			'filter' => ['type' => 'article'],
103			'labels' => array_combine(
104				$articleIds,
105				array_map(function ($id) {
106					return TikiLib::lib('object')->get_title('article', $id);
107				}, $articleIds)
108			),
109			'readonly' => $readonly,
110		]);
111	}
112
113	function renderOutput($context = [])
114	{
115		return $this->renderTemplate('trackeroutput/articles.tpl', $context, [
116		]);
117	}
118
119	function handleSave($value, $oldValue)
120	{
121		$new = array_diff(explode(',', $value), explode(',', $oldValue));
122		$remove = array_diff(explode(',', $oldValue), explode(',', $value));
123
124		$itemId = $this->getItemId();
125
126		$relationlib = TikiLib::lib('relation');
127		$relations = $relationlib->get_relations_from('trackeritem', $itemId, 'tiki.article.attach');
128		foreach ($relations as $existing) {
129			if ($existing['type'] != 'article') {
130				continue;
131			}
132
133			if (in_array($existing['itemId'], $remove)) {
134				$relationlib->remove_relation($existing['relationId']);
135			}
136		}
137
138		foreach ($new as $articleId) {
139			$relationlib->add_relation('tiki.article.attach', 'trackeritem', $itemId, 'article', $articleId);
140		}
141
142		return [
143			'value' => $value,
144		];
145	}
146
147	/**
148	 * This returns the document part for the article field in the trackeritem.
149	 * Note that this indexing only works as part of the rss aggregator feature.
150	 *
151	 * @param Search_Type_Factory_Interface $typeFactory
152	 * @return array
153	 */
154	function getDocumentPart(Search_Type_Factory_Interface $typeFactory)
155	{
156		global $prefs;
157		//if article indexing is set to off for tracker, just return an empty array here.
158		if ($prefs['tracker_article_indexing'] != 'y' || $prefs['tracker_article_trackerId'] != $this->getItemData()['trackerId']) {
159			return [];
160		}
161		$value = $this->getValue();
162		$baseKey = $this->getBaseKey();
163
164		if (! $value) {
165			return [];
166		}
167
168		if (empty($this->articleSource)) {
169			$this->articleSource = new Search_ContentSource_ArticleSource();
170		}
171
172		$articleInfo = $this->articleSource->getDocument($value, $typeFactory);
173		$data = [];
174		//append the article field to the base key. ie. tracker_field_articleField_title, tracker_field_articleField_author, etc
175		foreach ($articleInfo as $key => $v) {
176			$data[$baseKey . "_" . $key] = $v;
177		}
178		$data[$baseKey] = $typeFactory->identifier($value);
179		return $data;
180	}
181
182	function getProvidedFields()
183	{
184		$baseKey = $this->getBaseKey();
185
186		if (empty($this->articleSource)) {
187			$this->articleSource = new Search_ContentSource_ArticleSource();
188		}
189
190		$articleInfo = $this->articleSource->getProvidedFields();
191		$data = [];
192		foreach ($articleInfo as $k => $v) {
193			$data[$k] = $baseKey . '_' . $v;
194		}
195		$data[] = $baseKey;
196
197		return $data;
198	}
199
200	function getGlobalFields()
201	{
202		$baseKey = $this->getBaseKey();
203		return [$baseKey => true];
204	}
205}
206