1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
14:
15: defined('CON_FRAMEWORK') || die('Illegal call: Missing framework initialization - request aborted.');
16:
17: 18: 19: 20: 21: 22:
23: class cVersion {
24:
25: 26: 27: 28: 29:
30: protected $sType;
31:
32: 33: 34: 35: 36:
37: protected $sAuthor;
38:
39: 40: 41: 42: 43:
44: protected $dCreated;
45:
46: 47: 48: 49: 50:
51: protected $dLastModified;
52:
53: 54: 55: 56: 57:
58: protected $aBodyData;
59:
60: 61: 62: 63: 64:
65: protected $aCfg;
66:
67: 68: 69: 70: 71:
72: protected $aCfgClient;
73:
74: 75: 76: 77: 78:
79: protected $oDB;
80:
81: 82: 83: 84: 85:
86: protected $iClient;
87:
88: 89: 90: 91: 92:
93: public $aRevisionFiles;
94:
95: 96: 97: 98: 99:
100: protected $iRevisionNumber;
101:
102: 103: 104: 105: 106:
107: protected $dTimestamp;
108:
109: 110: 111: 112: 113:
114: protected $sArea;
115:
116: 117: 118: 119: 120:
121: protected $iFrame;
122:
123: 124: 125: 126: 127:
128: protected $aVarForm;
129:
130: 131: 132: 133: 134:
135: protected $iIdentity;
136:
137: 138: 139:
140: protected $sDescripion;
141:
142: 143: 144:
145: protected $iVersion;
146:
147: 148: 149: 150: 151:
152: private $bVersioningActive;
153:
154: 155: 156: 157: 158:
159: protected $dActualTimestamp;
160:
161: 162: 163: 164: 165:
166: protected $sAlternativePath;
167:
168: 169: 170: 171: 172:
173: public static $iDisplayNotification;
174:
175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187:
188: public function __construct($aCfg, $aCfgClient, $oDB, $iClient, $sArea, $iFrame) {
189: $this->aBodyData = array();
190: $this->aRevisionFiles = array();
191: $this->aCfg = $aCfg;
192:
193: $this->aCfgClient = $aCfgClient;
194:
195: $this->oDB = $oDB;
196: $this->iClient = $iClient;
197: $this->iRevisionNumber = 0;
198: $this->sArea = $sArea;
199: $this->iFrame = $iFrame;
200:
201: $this->dActualTimestamp = time();
202:
203: $this->aVarForm = array();
204:
205: self::$iDisplayNotification++;
206:
207:
208: if (function_exists('getEffectiveSetting')) {
209: $this->bVersioningActive = getEffectiveSetting('versioning', 'activated', 'true');
210: $this->sAlternativePath = getEffectiveSetting('versioning', 'path');
211:
212: if ($this->bVersioningActive == 'true') {
213: $this->bVersioningActive = true;
214: } else {
215: $this->bVersioningActive = false;
216: }
217: } else {
218: $this->bVersioningActive = true;
219: $this->sAlternativePath = '';
220: }
221:
222: if ($this->bVersioningActive == false) {
223: return;
224: }
225:
226: if (is_dir($this->sAlternativePath) == false) {
227:
228:
229: if ($this->sAlternativePath != '' and self::$iDisplayNotification < 2) {
230: $oNotification = new cGuiNotification();
231: $sNotification = i18n('Alternative path %s does not exist. Version was saved in frondendpath.');
232: $oNotification->displayNotification('warning', sprintf($sNotification, $this->sAlternativePath));
233: }
234:
235: $this->sAlternativePath = '';
236: }
237:
238:
239: $this->checkPaths();
240: }
241:
242: 243: 244: 245: 246: 247:
248: protected function prune() {
249: $this->initRevisions();
250: if (function_exists('getEffectiveSetting')) {
251: $sVar = getEffectiveSetting('versioning', 'prune_limit', '0');
252: } else {
253: $sVar = 0;
254: }
255:
256: $bDelete = true;
257:
258: while (count($this->aRevisionFiles) >= $sVar and $bDelete and (int) $sVar > 0) {
259: $iIndex = end(array_keys($this->aRevisionFiles));
260: $bDelete = $this->deleteFile($this->getFirstRevision());
261: unset($this->aRevisionFiles[$iIndex]);
262: }
263: }
264:
265: 266: 267: 268:
269: protected function checkPaths() {
270: $aPath = array(
271: '/',
272: 'css/',
273: 'js/',
274: 'layout/',
275: 'module/',
276: 'templates/'
277: );
278: $sFrontEndPath = '';
279: if ($this->sAlternativePath == '') {
280: $sFrontEndPath = $this->aCfgClient[$this->iClient]['version']['path'];
281: } else {
282: $sFrontEndPath = $this->sAlternativePath . '/' . $this->iClient . '/';
283: }
284:
285: foreach ($aPath as $sSubPath) {
286: if (!is_dir($sFrontEndPath . $sSubPath)) {
287: mkdir($sFrontEndPath . $sSubPath, cDirHandler::getDefaultPermissions());
288: @chmod($sFrontEndPath . $sSubPath, cDirHandler::getDefaultPermissions());
289: }
290: }
291: }
292:
293: 294: 295: 296: 297: 298: 299: 300:
301: public function setData($sKey, $sValue) {
302: $this->aBodyData[$sKey] = $sValue;
303: }
304:
305: 306: 307: 308: 309: 310: 311: 312: 313: 314: 315: 316:
317: public function createNewXml($sDirectory, $sFileName) {
318: $oWriter = new cXmlWriter();
319: $oRootElement = $oWriter->addElement('version', '', NULL, array(
320: 'xml:lang' => 'de'
321: ));
322: $oHeadElement = $oWriter->addElement('head', '', $oRootElement);
323:
324: $oWriter->addElement('version_id', $this->iIdentity . '_' . $this->iVersion, $oHeadElement);
325: $oWriter->addElement('type', $this->sType, $oHeadElement);
326: $oWriter->addElement('date', date('Y-m-d H:i:s'), $oHeadElement);
327: $oWriter->addElement('author', $this->sAuthor, $oHeadElement);
328: $oWriter->addElement('client', $this->iClient, $oHeadElement);
329: $oWriter->addElement('created', $this->dCreated, $oHeadElement);
330: $oWriter->addElement('lastmodified', $this->dLastModified, $oHeadElement);
331:
332: $oBodyElement = $oWriter->addElement('body', '', $oRootElement);
333: foreach ($this->aBodyData as $sKey => $sValue) {
334: $oWriter->addElement($sKey, $sValue, $oBodyElement, array(), true);
335: }
336:
337: return $oWriter->saveToFile($sDirectory, $sFileName);
338: }
339:
340: 341: 342: 343: 344: 345: 346:
347: public function createNewVersion() {
348: if ($this->bVersioningActive == false) {
349: return false;
350: }
351:
352:
353: $sRevisionName = $this->getRevision();
354:
355: if (!is_dir($this->getFilePath())) {
356: mkdir($this->getFilePath(), cDirHandler::getDefaultPermissions());
357: @chmod($this->getFilePath(), cDirHandler::getDefaultPermissions());
358: }
359:
360:
361: $bCreate = $this->createNewXml($this->getFilePath(), $sRevisionName . '.xml');
362:
363: if ($bCreate == false) {
364: throw new cException('Could not create new version.');
365: }
366:
367: return $bCreate;
368: }
369:
370: 371: 372: 373: 374: 375: 376:
377: protected function initRevisions() {
378: $this->aRevisionFiles = array();
379: $this->dTimestamp = array();
380:
381: $sDir = $this->getFilePath();
382: if (is_dir($sDir)) {
383: if (false !== ($handle = cDirHandler::read($sDir))) {
384: foreach ($handle as $file) {
385: if (false === cFileHandler::fileNameIsDot($file)) {
386: $aData = explode('.', $file);
387: $aValues = explode('_', $aData[0]);
388: if ($aValues[0] > $this->iRevisionNumber) {
389: $this->iRevisionNumber = $aValues[0];
390: }
391:
392: $this->dTimestamp[$aValues[0]] = $aValues[1];
393: $this->aRevisionFiles[$aValues[0]] = $file;
394: }
395: }
396: }
397: }
398:
399: return krsort($this->aRevisionFiles);
400: }
401:
402: 403: 404: 405: 406: 407: 408: 409:
410: public function deleteFile($sFirstFile = '') {
411:
412: $sDir = $this->getFilePath();
413:
414: $bDelete = true;
415: if (is_dir($sDir) and $sFirstFile == '') {
416: if (false !== ($handle = cDirHandler::read($sDir))) {
417: foreach ($handle as $sFile) {
418: if (false === cFileHandler::fileNameIsDot($sFile)) {
419:
420: if (false === cFileHandler::remove($sDir . $sFile)) {
421: $bDelete = false;
422: }
423: }
424: }
425:
426: if (true === $bDelete) {
427: $bDelete = cDirHandler::remove($sDir);
428: }
429: }
430: } else if ($sFirstFile != '') {
431: $bDelete = cFileHandler::remove($sDir . $sFirstFile);
432: }
433: if ($bDelete) {
434: return true;
435: } else {
436: return false;
437: }
438: }
439:
440: 441: 442: 443: 444: 445:
446: public function getFilePath() {
447: if ($this->sAlternativePath == '') {
448: $sFrontEndPath = $this->aCfgClient[$this->iClient]['version']['path'];
449: } else {
450: $sFrontEndPath = $this->sAlternativePath . '/' . $this->iClient . '/';
451: }
452: return $sFrontEndPath . $this->sType . '/' . $this->iIdentity . '/';
453: }
454:
455: 456: 457: 458: 459: 460:
461: public function getLastRevision() {
462: return reset($this->aRevisionFiles);
463: }
464:
465: 466: 467: 468: 469: 470:
471: private function getRevision() {
472: $this->iVersion = ($this->iRevisionNumber + 1) . '_' . $this->dActualTimestamp;
473: return $this->iVersion;
474: }
475:
476: 477: 478: 479: 480: 481:
482: protected function getFirstRevision() {
483: $this->initRevisions();
484: $aKey = $this->aRevisionFiles;
485: $sFirstRevision = '';
486:
487:
488: ksort($aKey);
489: foreach ($aKey as $value) {
490: return $sFirstRevision = $value;
491: }
492: return $sFirstRevision;
493: }
494:
495: 496: 497: 498: 499: 500:
501: public function getRevisionFiles() {
502: return $this->aRevisionFiles;
503: }
504:
505: 506: 507: 508: 509: 510:
511: public function getFormatTimestamp() {
512: $aTimes = array();
513: if (count($this->dTimestamp) > 0) {
514: krsort($this->dTimestamp);
515: foreach ($this->dTimestamp as $iKey => $sTimeValue) {
516: $aTimes[$this->aRevisionFiles[$iKey]] = date('d.m.Y H:i:s', $sTimeValue) . ' - Revision: ' . $iKey;
517: }
518: }
519:
520: return $aTimes;
521: }
522:
523: 524: 525: 526: 527: 528: 529: 530:
531: public function setVarForm($sKey, $sValue) {
532: $this->aVarForm[$sKey] = $sValue;
533: }
534:
535: 536: 537: 538: 539: 540: 541: 542: 543: 544: 545: 546: 547: 548: 549: 550: 551: 552: 553:
554: public function buildSelectBox($sTableForm, $sAddHeader, $sLabelOfSelectBox, $sIdOfSelectBox, $disabled = false) {
555: $oForm = new cGuiTableForm($sTableForm);
556:
557:
558: if (count($this->dTimestamp) > 0) {
559:
560: foreach ($this->aVarForm as $sKey => $sValue) {
561: $oForm->setVar($sKey, $sValue);
562: }
563: $aMessage = $this->getMessages();
564: $oForm->addHeader(i18n($sAddHeader));
565: $oForm->add(i18n($sLabelOfSelectBox), $this->getSelectBox($this->getFormatTimestamp(), $sIdOfSelectBox));
566: $oForm->setActionButton('clearhistory', 'images/delete' . (($disabled) ? '_inact' : '') . '.gif', $aMessage['alt'], 'c', 'history_truncate');
567: if(!$disabled) {
568: $oForm->setConfirm('clearhistory', $aMessage['alt'], $aMessage['popup']);
569: }
570: $oForm->setActionButton('submit', 'images/but_refresh.gif', i18n('Refresh'), 's');
571: $oForm->setTableID("version_selector");
572:
573: return $oForm->render();
574: } else {
575: return '';
576: }
577: }
578:
579: 580: 581: 582: 583: 584: 585:
586: private function getMessages() {
587: $aMessage = array();
588: switch ($this->sType) {
589: case 'layout':
590: $aMessage['alt'] = i18n('Clear layout history');
591: $aMessage['popup'] = i18n('Do you really want to clear layout history?') . '<br><br>' . i18n('Note: This only affects the current layout.');
592: break;
593: case 'module':
594: $aMessage['alt'] = i18n('Clear module history');
595: $aMessage['popup'] = i18n('Do you really want to clear module history?') . '<br><br>' . i18n('Note: This only affects the current module.');
596: break;
597: case 'css':
598: $aMessage['alt'] = i18n('Clear style history');
599: $aMessage['popup'] = i18n('Do you really want to clear style history?') . '<br><br>' . i18n('Note: This only affects the current style.');
600: break;
601: case 'js':
602: $aMessage['alt'] = i18n('Clear Java-Script history');
603: $aMessage['popup'] = i18n('Do you really want to clear Java-Script history?') . '<br><br>' . i18n('Note: This only affects the current JavaScript.');
604: break;
605: case 'templates':
606: $aMessage['alt'] = i18n('Clear HTML template history');
607: $aMessage['popup'] = i18n('Do you really want to clear HTML template history?') . '<br><br>' . i18n('Note: This only the affects current HTML template.');
608: break;
609: default:
610: $aMessage['alt'] = i18n('Clear history');
611: $aMessage['popup'] = i18n('Do you really want to clear history?') . '<br><br>' . i18n('Note: This only affects the current history.');
612: break;
613: }
614: return $aMessage;
615: }
616:
617: 618: 619: 620: 621: 622: 623: 624: 625: 626:
627: private function getSelectBox($aTempVesions, $sIdOfSelectBox) {
628: $sSelected = $_POST[$sIdOfSelectBox];
629: $oSelectMenue = new cHTMLSelectElement($sIdOfSelectBox);
630: $oSelectMenue->autoFill($aTempVesions);
631:
632: if ($sSelected != '') {
633: $oSelectMenue->setDefault($sSelected);
634: }
635:
636: return $oSelectMenue->render();
637: }
638:
639: 640: 641: 642: 643: 644: 645: 646: 647: 648: 649: 650: 651: 652: 653: 654: 655:
656: public function getTextarea($sName, $sInitValue, $iWidth, $iHeight, $sId = '', $disabled = false) {
657: if ($sId != '') {
658: $oHTMLTextarea = new cHTMLTextarea($sName, $sInitValue, $iWidth, $iHeight, $sId);
659: } else {
660: $oHTMLTextarea = new cHTMLTextarea($sName, $sInitValue, $iWidth, $iHeight);
661: }
662:
663: if ($disabled) {
664: $oHTMLTextarea->setDisabled('disabled');
665: }
666:
667: $oHTMLTextarea->setStyle('font-family: monospace; width: 100%;');
668: $oHTMLTextarea->updateAttributes(array(
669: 'wrap' => 'off'
670: ));
671:
672: return $oHTMLTextarea->render();
673: }
674:
675: 676: 677: 678: 679: 680: 681: 682: 683: 684: 685: 686: 687: 688:
689: public function getTextBox($sName, $sInitValue, $iWidth, $bDisabled = false) {
690: $oHTMLTextbox = new cHTMLTextbox($sName, conHtmlEntityDecode($sInitValue), $iWidth, '', '', $bDisabled);
691: $oHTMLTextbox->setStyle('font-family:monospace; width:100%;');
692: $oHTMLTextbox->updateAttributes(array(
693: 'wrap' => 'off'
694: ));
695:
696: return $oHTMLTextbox->render();
697: }
698:
699: 700: 701: 702: 703:
704: public function displayNotification($sOutPut) {
705: if ($sOutPut != '') {
706: print $sOutPut;
707: }
708: }
709:
710: 711: 712: 713: 714: 715:
716: public function setBodyNodeDescription($sDesc) {
717: if ($sDesc != '') {
718: $this->sDescripion = conHtmlentities($sDesc);
719: $this->setData('description', $this->sDescripion);
720: }
721: }
722:
723: }
724: