Gentics Portal.Node PHP API
 All Classes Namespaces Functions Variables Pages
DynamicContentSource.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 loading content from Dynamic Content Renderer
11  */
13 {
14  /**
15  * @var string folder into which content will be cached
16  */
17  public $cacheFolder;
18 
19  private $_modTimeCachePrefix = '__modTime__';
20 
21  /**
22  * Init Gentics Connector API
23  */
24  public function init()
25  {
26 
27  }
28 
29  /**
30  * Return array of attributes which will be requested from API
31  *
32  * @return array array of attributes
33  */
34  public function getRequestedAttributes()
35  {
36  $mainAttributes = array(
37  'contentid',
38  'name',
39  'filename',
40  'updatetimestamp',
41  'languagecode',
42  'mimetype',
43  'content'
44  );
45  if ($this->usePersonalisation) {
46  return array_merge($mainAttributes, $this->personalisationFields);
47  }
48  return $mainAttributes;
49  }
50 
51  /**
52  * Get content absolute path.
53  * Checking if we have newest version on content,
54  * if yes return, else download and store
55  *
56  * @param string $path content path
57  *
58  * @return \Content|mixed object contained file path, false if error
59  */
60  public function getContent($path)
61  {
62  if ($this->_haveNewestVersion($path)) {
63  return $this->_takeFromFileSystem($path);
64  } else {
65  return $this->_takeAndSaveFromApi($path);
66  }
67  }
68 
69  public function getStartPage($folderPath, $locale)
70  {
71  $localizedAttributeName = Yii::app()->getModule('contentSource')->localizedAttributeName. $locale;
72 
73  $folderObject = $this->getRepositoryApi()->getContentAttributes($folderPath, array($localizedAttributeName));
74  if($folderObject){
75  return $folderObject[$localizedAttributeName];
76  }
77  return false;
78  }
79 
80  /**
81  * This method takes content from API and save locally
82  *
83  * @param string $path content path
84  *
85  * @return bool|string
86  */
87  private function _takeAndSaveFromApi($path)
88  {
89  // if refresh is set
90  if ( Yii::app()->request->getParam('refresh') == true) {
91  $cmsObject = $this->getRepositoryApi()->getCmsObjectCanBeExternal($path, $this->getRequestedAttributes());
92  // clear cache of object in CCR
93  $this->getRepositoryApi()->clearCache($cmsObject['attributes']['contentid']);
94  }
95  // get content object from CCR
96  if ($cmsObject = $this->getRepositoryApi()->getCmsObjectCanBeExternal($path, $this->getRequestedAttributes())) {
97  // create new cache file
98  $this->_createFile($path, $cmsObject['attributes']['content'], $cmsObject['attributes']['updatetimestamp']);
99  // create new content object
100  $content = new Content($this, $path);
101  unset($cmsObject['attributes']['content']);
102  $content->setAttributes($cmsObject['attributes']);
103  return $content;
104  }
105 
106  return false;
107  }
108 
109  /**
110  * Checking if we have latest version of file
111  *
112  * @param string $path content path
113  *
114  * @return bool
115  */
116  private function _haveNewestVersion($path)
117  {
118  // path alone seems to be not enough, host must be added to the cache key TODO
119  // get path of file in fs cache
120  $contentFile = $this->contentFile($path);
121 
122  // if file is not in fs cache, then get from api
123  if (!file_exists($contentFile) || Yii::app()->request->getParam('refresh', false)) {
124  return false;
125  }
126 
127  // if no cache of modification timestamp of file is set OR an editorsession is aktiv and the session is not 0, then request new update timestamp of file in CCR
128  // we don't cache in case a CMS editor is in the portal because of instant publishing
129  if ( ( Yii::app()->cache->get("lastcheck_".$this->_modTimeCachePrefix . $path) === false ) ||
130  ( Yii::app()->session->get('feSid',false) && Yii::app()->session->get('feSid', false) ) ) {
131 
132  // set cache for last modification timestamp of file only for a short time (to prevent reloading)
133  Yii::app()->cache->set("lastcheck_".$this->_modTimeCachePrefix . $path , time(), Yii::app()->getModule('contentSource')->cacheTime);
134 
135  // get modification timestamp from CCR for this file
136  if ($lastModificationTime = $this->getRepositoryApi()->getLastModificationTime($path)) {
137  Yii::trace( "$lastModificationTime " . Yii::app()->cache->get($this->_modTimeCachePrefix . $path) . " " . filemtime($this->contentFile($path)), "myoutput");
138  //return true if timestamp from cache is the same as timestamp from CCR for this path OR if modification timestamp of file in fs cache is the same as timestamp of CCR //return Yii::app()->cache->get("lastcheck_".$this->_modTimeCachePrefix . $path) == $lastModificationTime || filemtime($this->contentFile($path)) == $lastModificationTime;
139  if ( Yii::app()->cache->get("lastcheck_".$this->_modTimeCachePrefix . $path) == $lastModificationTime || filemtime($this->contentFile($path)) == $lastModificationTime ) {
140  return true;
141  } else {
142  @unlink( $contentFile );
143  return false;
144  }
145  }
146  } else {
147  return true;
148  }
149 
150  @unlink( $contentFile );
151  return false;
152  }
153 
154  /**
155  * Take existed file from filesystem
156  *
157  * @param string $path content path
158  *
159  * @return bool|string
160  */
161  private function _takeFromFileSystem($path)
162  {
163  $contentFile = $this->contentFile($path);
164  if ($this->fileAccessible($contentFile, $this->cacheFolder)) {
165  $content = new Content($this, $path);
166  return $content;
167  } else {
168  return false;
169  }
170  }
171 
172 
173  /**
174  * Create file,and save its last modification date
175  *
176  * @param string $path string relative path
177  * @param string $content string file content
178  * @param int $time mixed last modification time
179  *
180  * @throws Exception
181  * @return string string absolute path
182  *
183  */
184  private function _createFile($path, $content, $time)
185  {
186  $contentFile = $this->contentFile($path);
187  if (file_exists($contentFile) && !$this->fileAccessible($contentFile, $this->cacheFolder)) {
188  return false;
189  }
190 
191  $dirPath = pathinfo($contentFile, PATHINFO_DIRNAME);
192  if (!file_exists($dirPath)) {
193  if (!@mkdir($dirPath, 0777, true)) {
194  throw new Exception("Can't create dir $dirPath");
195  }
196  }
197  if (!file_put_contents($contentFile, $content)) {
198  throw new Exception("Can't create file $contentFile");
199  }
200  if (!touch($contentFile, $time)) {
201  throw new Exception("Can't touch() file $contentFile");
202  }
203  if (!chmod($contentFile, 0666)) {
204  throw new Exception("Can't chmod() file $contentFile");
205  }
206 
207  if (!$this->fileAccessible($contentFile, $this->cacheFolder)) {
208  unlink($contentFile);
209  return false;
210  }
211 
212  Yii::app()->cache->set($this->_modTimeCachePrefix . $path, $time, Yii::app()->getModule('contentSource')->cacheTime);
213 
214  return $contentFile;
215  }
216 
217  /**
218  * Get content file location
219  *
220  * @param string $path content path
221  *
222  * @return string
223  */
224  public function contentFile($path)
225  {
226  return $this->cacheFolder . $path;
227  }
228 
229 
230 }