Gentics Portal.Node PHP API
 All Classes Namespaces Functions Variables Pages
TagcloudApi.php
1 <?php
2 /**
3  * Gentics Portal.Node PHP
4  * Author & Copyright (c) by Gentics Software GmbH
5  * sales@gentics.com
6  * http://www.gentics.com
7  * Licenses can be found in the LICENSE.txt file in the root-folder of this installation
8  * You must not use this software without a valid license agreement.
9  *
10  * Class for working with Gentics Content Connector
11  */
12 class TagcloudApi extends CComponent
13 {
14 
15  /**
16  * @var array $folderIds contains folder IDs of content to show
17  */
18  public $folderIds;
19 
20  /**
21  * @var string $lang contains current languagecode
22  */
23  public $lang;
24 
25  /**
26  * array that contains received data
27  * @var $data
28  */
29  public $data = array();
30 
31  /**
32  * array that contains extracted tags
33  *
34  * @var $tags
35  */
36  public $tags = array();
37 
38  /**
39  * @var bool $usePersonalisation defines if personalisation should be performed
40  */
41  public $usePersonalisation = true;
42 
43  /**
44  * @var string $htmlCacheKey contains cacheKey that can be used for HTML caching
45  */
46  public $htmlCacheKey = '';
47 
48  /**
49  * @var string $overviewPage CMS page with overview widget
50  */
51  public $overviewPage;
52 
53  /**
54  * @var string tagstyles
55  */
56  public $tagstyles = array();
57 
58  /**
59  * @var string tagsSeparator
60  */
61  public $tagsSeparator = ', ';
62 
63  /**
64  * Performs GCC request, filters data by personalisation rules and extacts tags from received data
65  *
66  * @return void|bool
67  */
68  public function run($limit = null)
69  {
70  //Yii::app()->cache->flush();
71 
72  if (!empty($this->folderIds)) {
73  sort($this->folderIds);
74 
75  $this->_loadData();
76  $this->_cleanUp(Yii::app()->user->id);
77  $this->_extractTags($limit);
78 
79  return true;
80 
81  } else {
82  return false;
83  }
84  }
85 
86  /**
87  * Extracts tags from loaded data
88  *
89  * @return bool
90  */
91  private function _extractTags($limit = null)
92  {
93  if (empty($this->data)) {
94  return false;
95  }
96 
97  $this->tags = array();
98 
99  foreach ($this->data as $entry) {
100  if (!empty($entry['attributes']['tagging'])) {
101  $tags = explode($this->tagsSeparator, $entry['attributes']['tagging']);
102 
103  foreach ($tags as $tag) {
104  $tag = trim($tag);
105  $this->tags[$tag] = empty($this->tags[$tag]) ? 1 : $this->tags[$tag]+1;
106  }
107  }
108  }
109 
110  Yii::trace('Tags and usage: '.print_r($this->tags, true), 'Api requests(start)');
111 
112  if (!empty($this->tags)) {
113 
114  arsort($this->tags);
115  reset($this->tags);
116 
117  if(isset($limit)) {
118  $this->tags = array_slice($this->tags, 0 ,$limit);
119  }
120 
121  $tagstylesQty = count($this->tagstyles);
122  $max = max($this->tags);
123  $step = ceil($max / count($this->tagstyles));
124 
125  foreach ($this->tags as $k=>$v) {
126  $index = round($v/$step);
127  $index = $index<=($tagstylesQty-1) ? $index : $index-1;
128 
129  $url = $this->overviewPage;
130  $url .= strpos($url, '?')!==false ? '&tag='.$k : '?tag='.$k;
131  $url .= '&folderIds='.str_replace('10002.', '', implode(',', $this->folderIds));
132 
133  $this->tags[$k] = array(
134  'class' => $this->tagstyles[$index],
135  'url' => $url,
136  );
137  }
138  }
139 
140  return true;
141  }
142 
143  /**
144  * Filter data by some schema
145  *
146  * @param integer $user_id Id of the user to personalize tree for
147  *
148  * @return array
149  */
150  private function _cleanUp($user_id)
151  {
152  $maxTimestamp = $this->loadMaxUpdatetimestamp();
153  $cacheId = 'tagcloud_PERS_'.md5(implode(',', $this->folderIds).$this->lang.$maxTimestamp.intval($this->usePersonalisation));
154  $this->htmlCacheKey = 'tagcloud_HTML_'.md5(implode(',', $this->folderIds).implode(',', $this->tagstyles).$this->lang.$maxTimestamp.intval($this->usePersonalisation).$this->overviewPage.$this->tagsSeparator);
155 
156  if (($data = Yii::app()->cache->get($cacheId)) === false) {
157  //get personalisation fields from settings
158  $filters = $this->getFiltersList();
159  $data = array();
160 
161  // apply filter here
162  if ($filters && $this->data) {
163  foreach ($this->data as $id=>$contentPage) {
164  if (!is_null($this->_unsetNodes($filters, $user_id, $contentPage))) {
165  $data[$id] = $contentPage;
166  }
167  }
168  }
169 
170  $this->data = $data;
171 
172  Yii::app()->cache->set($cacheId, $this->data);
173  } else {
174  $this->data = $data;
175  }
176  }
177 
178  /**
179  * Private method that will unset not allowed data
180  *
181  * @param array $filters contains keys that will be used as filters
182  * @param array $user_id contains user permissions
183  * @param array $data points to the array with nodes tree
184  *
185  * @return array|null
186  */
187  private function _unsetNodes($filters, $user_id, $data)
188  {
189  /* check permissions for current node */
190  $persAttributes = array();
191  foreach ($filters as $filter) {
192  if (!empty($data['attributes'][$filter])) {
193  $persAttributes = array_merge($persAttributes, $data['attributes'][$filter]);
194  }
195  }
196 
197  // Call function that will check permissions
198  if ($this->usePersonalisation) {
199  if (!Yii::app()->getModule('personalisation')->rule->checkAccess($user_id, $persAttributes)) {
200  /* if user does not have permissions - unset the node */
201  return null;
202  }
203  }
204 
205  return $data;
206  }
207 
208  /**
209  * Filter tree by some schema
210  *
211  * @return array|bool
212  */
213  public function getFiltersList()
214  {
215  if (Yii::app()->getModule('contentSource')->contentSource->usePersonalisation) {
216  $filters = Yii::app()->getModule('contentSource')->contentSource->personalisationFields;
217  return $filters;
218  }
219 
220  return false;
221  }
222 
223  /**
224  * Load required tree data from cache. If not exists request Gentics Content Connector API for a new tree.
225  *
226  * @return array
227  */
228  private function _loadData()
229  {
230  $data = array();
231  $filtersList = '';
232  $requertFields = array(
233  'edittimestamp',
234  'tagging'
235  );
236 
237  // get max timestamp for given folderIds
238  $maxTimestamp = $this->loadMaxUpdatetimestamp();
239 
240  // create cache key that includes folderIds+language+gccRequestString+timestamp of last updated folder;
241  $cacheId = 'tagcloud_'.md5(implode(',', $this->folderIds).$this->lang.$maxTimestamp);
242 
243  // Load data
244  if (($data = Yii::app()->cache->get($cacheId)) === false) {
245  $data = Yii::app()->repositoryApi->request(
246  array(
247  'filter' => 'object.obj_type==10007 AND object.languagecode=="'.$this->lang.'" AND (object.folder_id=="'.implode('" OR object.folder_id=="', $this->folderIds).'")',
248  'type' => 'php',
249  ),
250  CMap::mergeArray($this->getFiltersList(), $requertFields)
251  );
252  $data = unserialize($data);
253 
254  if (isset($data['status']) && $data['status'] == 'ok') {
255  unset($data['status']);
256  } else {
257  $data = array();
258  }
259  Yii::app()->cache->set($cacheId, $data);
260  }
261 
262  $this->data = $data;
263  }
264 
265  /**
266  * extracts max updatetimestamp from array of CMS objects
267  *
268  * @return int|bool
269  */
270  public function loadMaxUpdatetimestamp()
271  {
272  // TODO cachekey is wrong - should only be cached for $cacheTime
273  $timestampCacheId = 'tagcloud_UTS_'.md5(implode(',', $this->folderIds).$this->lang);
274 
275  //try to get $maxTimestamp from cache
276  if (($maxTimestamp = Yii::app()->cache->get($timestampCacheId)) === false) {
277 
278  $timestamps = Yii::app()->repositoryApi->request(
279  array(
280  'filter' => 'object.contentid=="'.implode('" OR object.contentid=="', $this->folderIds).'"',
281  'type' => 'php',
282  'sorting' => 'updatetimestamp:desc',
283  'count' => '1'
284 
285  ),
286  array('updatetimestamp')
287  );
288  $timestamps = unserialize($timestamps);
289 
290  if (isset($timestamps['status']) && $timestamps['status']=='ok') {
291  unset($timestamps['status']);
292  $maxTimestamp = 0;
293  foreach ($timestamps as $id=>$contentFolder) {
294  if (isset($contentFolder['attributes']['updatetimestamp']) && $contentFolder['attributes']['updatetimestamp'] > $maxTimestamp) {
295  $maxTimestamp = $contentFolder['attributes']['updatetimestamp'];
296  }
297  }
298 
299  Yii::app()->cache->set($timestampCacheId, $maxTimestamp, Yii::app()->getModule('tagcloud')->cacheTime);
300  } else {
301  $maxTimestamp = false;
302  }
303  }
304  return $maxTimestamp;
305  }
306 }