Gentics Portal.Node PHP API
 All Classes Namespaces Functions Variables Pages
PersonalizedContent.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 PersonalizedContent 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 $gccRequestParams contains parameters that should be requested fron GCC
22  */
23  public $gccRequestParams;
24 
25  /**
26  * @var string $lang contains current languagecode
27  */
28  public $lang;
29 
30  /**
31  * @var string $tag contains content required tag
32  */
33  public $tag;
34 
35  /**
36  * array that contains categories tree
37  * @var $data
38  */
39 
40  public $data = array();
41 
42  /**
43  * @var string $sorting contains sorting expression
44  */
45  public $sorting;
46 
47  /**
48  * @var bool $usePersonalisation defines if personalisation should be performed
49  */
50  public $usePersonalisation = true;
51 
52  /**
53  * Construction that will load nodes tree for given $folderIds
54  *
55  * @param array $folderIds contains folder IDs of content to show
56  * @param bool $usePersonalisation determines if personalization should be performed
57  * @param string $tag content tag
58  *
59  * @return \personalizedContent
60  */
61  public function __construct($folderIds = array(), $usePersonalisation = true, $tag = '', $gccRequestParams = null, $sorting = null)
62  {
63 
64  //Yii::app()->cache->flush();
65 
66  if (!empty($folderIds)) {
67 
68  $this->lang = substr(Yii::app()->language, 0, 2);
69  $this->gccRequestParams = isset($gccRequestParams)? $gccRequestParams : Yii::app()->getModule('personalizedContent')->gccRequestParams;
70  $this->sorting = isset($sorting)? $sorting : Yii::app()->getModule('personalizedContent')->sorting;
71  $this->usePersonalisation = $usePersonalisation;
72  $this->tag = $tag;
73 
74  $this->folderIds = $folderIds;
75  sort($this->folderIds);
76 
77  $this->_loadData();
78  $this->_cleanUp(Yii::app()->user->id);
79 
80  } else {
81  return false;
82  }
83  }
84 
85  /**
86  * Filter tree by some schema
87  *
88  * @param integer $user_id Id of the user to personalize tree for
89  *
90  * @return array
91  */
92  private function _cleanUp($user_id)
93  {
94  $maxTimestamp = $this->loadMaxUpdatetimestamp();
95  $cacheId = 'persContent_PERS_'.md5(implode(',', $this->folderIds).$this->lang.$this->gccRequestParams.$this->sorting.$maxTimestamp.$this->tag);
96 
97  if (($data = Yii::app()->cache->get($cacheId)) === false) {
98  //get personalisation fields from settings
99  $filters = $this->getFiltersList();
100  $data = array();
101 
102  // apply filter here
103  if ($filters && $this->data) {
104  foreach ($this->data as $id=>$contentPage) {
105  if (!is_null($this->_unsetNodes($filters, $user_id, $contentPage))) {
106  $data[$id] = $contentPage;
107  }
108  }
109  }
110 
111  $this->data = $data;
112 
113  Yii::app()->cache->set($cacheId, $this->data);
114  } else {
115  $this->data = $data;
116  }
117  }
118 
119  /**
120  * Private method that will unset not allowed data
121  *
122  * @param array $filters contains keys that will be used as filters
123  * @param array $user_id contains user permissions
124  * @param array $data points to the array with nodes tree
125  *
126  * @return array|null
127  */
128  private function _unsetNodes($filters, $user_id, $data)
129  {
130  /* check permissions for current node */
131  $persAttributes = array();
132  foreach ($filters as $filter) {
133  if (!empty($data['attributes'][$filter])) {
134  $persAttributes = array_merge($persAttributes, $data['attributes'][$filter]);
135  }
136  }
137 
138  //check if page has allowed startpageurl and exlude the branch if it does not.
139  if ($data['contentid'] != in_array($data['contentid'], $this->folderIds)) {
140  $excludeURLs = Yii::app()->getModule('personalizedContent')->excludeURLs;
141  if ((isset($data['attributes']['url']) && in_array($data['attributes']['url'], $excludeURLs)) || !isset($data['attributes']['url'])) {
142  return null;
143  }
144  }
145 
146  // Call function that will check permissions
147  if ($this->usePersonalisation) {
148  if (!Yii::app()->getModule('personalisation')->rule->checkAccess($user_id, $persAttributes)) {
149  /* if user does not have permissions - unset the node */
150  return null;
151  }
152  }
153 
154  return $data;
155  }
156 
157  /**
158  * Filter tree by some schema
159  *
160  * @return array|bool
161  */
162  public function getFiltersList()
163  {
164  if (Yii::app()->getModule('contentSource')->contentSource->usePersonalisation) {
165  $filters = Yii::app()->getModule('contentSource')->contentSource->personalisationFields;
166  return $filters;
167  }
168 
169  return false;
170  }
171 
172  /**
173  * Load required tree data from cache. If not exists request Gentics Content Connector API for a new tree.
174  *
175  * @return array
176  */
177  private function _loadData()
178  {
179  $data = array();
180  $filtersList = '';
181 
182  $this->gccRequestParams = rtrim($this->gccRequestParams, ',');
183  $requertFields = explode(',', $this->gccRequestParams);
184 
185  $requertFields[] = 'updatetimestamp';
186  $requertFields[] = 'name';
187  $requertFields[] = 'url';
188 
189  $requertFields = array_unique($requertFields);
190 
191  // get max timestamp for given folderIds
192  $maxTimestamp = $this->loadMaxUpdatetimestamp();
193 
194  //create cache key that includes folderIds+language+gccRequestString+timestamp of last updated folder;
195  $cacheId = 'persContent_'.md5(implode(',', $this->folderIds).$this->lang.$this->gccRequestParams.$maxTimestamp.$this->tag);
196 
197  //Load data
198  if (($data = Yii::app()->cache->get($cacheId)) === false) {
199  $params = array(
200  'filter' => 'object.obj_type==10007 AND object.hideinoverview != 1 AND object.languagecode=="'.$this->lang.'" AND (object.folder_id=="'.implode('" OR object.folder_id=="', $this->folderIds).'")',
201  'type' => 'php',
202  'sorting' => $this->sorting,
203  );
204 
205  if (!empty($this->tag)) {
206  $params['filter'] .= 'AND object.tagging LIKE "*'.$this->tag.'*"';
207  }
208 
209  $params = Yii::app()->getComponent('repositoryApi')->addAdditionalParameters($params, 'contentRepositorySearch');
210 
211  $data = Yii::app()->repositoryApi->request(
212  $params,
213  CMap::mergeArray($this->getFiltersList(), $requertFields)
214  );
215  $data = unserialize($data);
216 
217  if (isset($data['status']) && $data['status'] == 'ok') {
218  unset($data['status']);
219  } else {
220  $data = array();
221  }
222 
223  Yii::app()->cache->set($cacheId, $data);
224  }
225 
226  $this->data = $data;
227  }
228 
229  /**
230  * extracts max updatetimestamp from array of CMS objects
231  *
232  * @return int|bool
233  */
234  public function loadMaxUpdatetimestamp()
235  {
236  $timestampCacheId = 'persContent_UTS_'.md5(implode(',', $this->folderIds).$this->lang.$this->gccRequestParams.$this->sorting.$this->tag);
237 
238  //try to get $maxTimestamp from cache
239  if (($maxTimestamp = Yii::app()->cache->get($timestampCacheId)) === false) {
240  $params = array(
241  'filter' => 'object.obj_type==10007 AND object.hideinoverview != 1 AND object.languagecode=="'.$this->lang.'" AND (object.folder_id=="'.implode('" OR object.folder_id=="', $this->folderIds).'")',
242  'type' => 'php',
243  'sorting' => $this->sorting,
244  );
245  if (!empty($this->tag)) {
246  $params['filter'] .= 'AND object.tagging LIKE "*'.$this->tag.'*"';
247  }
248 
249  $params = Yii::app()->getComponent('repositoryApi')->addAdditionalParameters($params, 'contentRepositorySearch');
250 
251  $timestamps = Yii::app()->repositoryApi->request(
252  $params,
253  array('updatetimestamp')
254  );
255  $timestamps = unserialize($timestamps);
256 
257  if (isset($timestamps['status']) && $timestamps['status']=='ok') {
258  unset($timestamps['status']);
259  $maxTimestamp = 0;
260  foreach ($timestamps as $id=>$contentFolder) {
261  if (isset($contentFolder['attributes']['updatetimestamp']) && $contentFolder['attributes']['updatetimestamp'] > $maxTimestamp) {
262  $maxTimestamp = $contentFolder['attributes']['updatetimestamp'];
263  }
264  }
265 
266  Yii::app()->cache->set($timestampCacheId, $maxTimestamp, Yii::app()->getModule('personalizedContent')->cacheTime);
267  } else {
268  $maxTimestamp = false;
269  }
270  }
271  return $maxTimestamp;
272  }
273 }