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: public function __construct($aCfg, $aCfgClient, $oDB, $iClient, $sArea, $iFrame) {
188: $this->aBodyData = array();
189: $this->aRevisionFiles = array();
190: $this->aCfg = $aCfg;
191:
192: $this->aCfgClient = $aCfgClient;
193:
194: $this->oDB = $oDB;
195: $this->iClient = $iClient;
196: $this->iRevisionNumber = 0;
197: $this->sArea = $sArea;
198: $this->iFrame = $iFrame;
199:
200: $this->dActualTimestamp = time();
201:
202: $this->aVarForm = array();
203:
204: self::$iDisplayNotification++;
205:
206:
207: if (function_exists('getEffectiveSetting')) {
208: $this->bVersioningActive = getEffectiveSetting('versioning', 'activated', 'true');
209: $this->sAlternativePath = getEffectiveSetting('versioning', 'path');
210:
211: if ($this->bVersioningActive == 'true') {
212: $this->bVersioningActive = true;
213: } else {
214: $this->bVersioningActive = false;
215: }
216: } else {
217: $this->bVersioningActive = true;
218: $this->sAlternativePath = '';
219: }
220:
221: if ($this->bVersioningActive == false) {
222: return;
223: }
224:
225: if (is_dir($this->sAlternativePath) == false) {
226:
227:
228: if ($this->sAlternativePath != '' and self::$iDisplayNotification < 2) {
229: $oNotification = new cGuiNotification();
230: $sNotification = i18n('Alternative path %s does not exist. Version was saved in frondendpath.');
231: $oNotification->displayNotification('warning', sprintf($sNotification, $this->sAlternativePath));
232: }
233:
234: $this->sAlternativePath = '';
235: }
236:
237:
238: $this->checkPaths();
239: }
240:
241: 242: 243: 244:
245: protected function prune() {
246: $this->initRevisions();
247: if (function_exists('getEffectiveSetting')) {
248: $sVar = getEffectiveSetting('versioning', 'prune_limit', '0');
249: } else {
250: $sVar = 0;
251: }
252:
253: $bDelete = true;
254:
255: while (count($this->aRevisionFiles) >= $sVar and $bDelete and (int) $sVar > 0) {
256: $iIndex = end(array_keys($this->aRevisionFiles));
257: $bDelete = $this->deleteFile($this->getFirstRevision());
258: unset($this->aRevisionFiles[$iIndex]);
259: }
260: }
261:
262: 263: 264: 265:
266: protected function checkPaths() {
267: $aPath = array(
268: '/',
269: 'css/',
270: 'js/',
271: 'layout/',
272: 'module/',
273: 'templates/'
274: );
275: $sFrontEndPath = '';
276: if ($this->sAlternativePath == '') {
277: $sFrontEndPath = $this->aCfgClient[$this->iClient]['version']['path'];
278: } else {
279: $sFrontEndPath = $this->sAlternativePath . '/' . $this->iClient . '/';
280: }
281:
282: foreach ($aPath as $sSubPath) {
283: if (!is_dir($sFrontEndPath . $sSubPath)) {
284: mkdir($sFrontEndPath . $sSubPath, 0777);
285: @chmod($sFrontEndPath . $sSubPath, 0777);
286: }
287: }
288: }
289:
290: 291: 292: 293: 294: 295: 296: 297:
298: public function setData($sKey, $sValue) {
299: $this->aBodyData[$sKey] = $sValue;
300: }
301:
302: 303: 304: 305: 306: 307: 308: 309: 310: 311:
312: public function createNewXml($sDirectory, $sFileName) {
313: $oWriter = new cXmlWriter();
314: $oRootElement = $oWriter->addElement('version', '', NULL, array(
315: 'xml:lang' => 'de'
316: ));
317: $oHeadElement = $oWriter->addElement('head', '', $oRootElement);
318:
319: $oWriter->addElement('version_id', $this->iIdentity . '_' . $this->iVersion, $oHeadElement);
320: $oWriter->addElement('type', $this->sType, $oHeadElement);
321: $oWriter->addElement('date', date('Y-m-d H:i:s'), $oHeadElement);
322: $oWriter->addElement('author', $this->sAuthor, $oHeadElement);
323: $oWriter->addElement('client', $this->iClient, $oHeadElement);
324: $oWriter->addElement('created', $this->dCreated, $oHeadElement);
325: $oWriter->addElement('lastmodified', $this->dLastModified, $oHeadElement);
326:
327: $oBodyElement = $oWriter->addElement('body', '', $oRootElement);
328: foreach ($this->aBodyData as $sKey => $sValue) {
329: $oWriter->addElement($sKey, $sValue, $oBodyElement, array(), true);
330: }
331:
332: return $oWriter->saveToFile($sDirectory, $sFileName);
333: }
334:
335: 336: 337: 338: 339: 340: 341:
342: public function createNewVersion() {
343: if ($this->bVersioningActive == false) {
344: return false;
345: }
346:
347:
348: $sRevisionName = $this->getRevision();
349:
350: if (!is_dir($this->getFilePath())) {
351: mkdir($this->getFilePath(), 0777);
352: @chmod($this->getFilePath(), 0777);
353: }
354:
355:
356: $bCreate = $this->createNewXml($this->getFilePath(), $sRevisionName . '.xml');
357:
358: if ($bCreate == false) {
359: throw new cException('Could not create new version.');
360: }
361:
362: return $bCreate;
363: }
364:
365: 366: 367: 368: 369: 370: 371:
372: protected function initRevisions() {
373: $this->aRevisionFiles = array();
374: $this->dTimestamp = array();
375:
376: $sDir = $this->getFilePath();
377: if (is_dir($sDir)) {
378: if (false !== ($handle = cDirHandler::read($sDir))) {
379: foreach ($handle as $file) {
380: if (false === cFileHandler::fileNameIsDot($file)) {
381: $aData = explode('.', $file);
382: $aValues = explode('_', $aData[0]);
383: if ($aValues[0] > $this->iRevisionNumber) {
384: $this->iRevisionNumber = $aValues[0];
385: }
386:
387: $this->dTimestamp[$aValues[0]] = $aValues[1];
388: $this->aRevisionFiles[$aValues[0]] = $file;
389: }
390: }
391: }
392: }
393:
394: return krsort($this->aRevisionFiles);
395: }
396:
397: 398: 399: 400: 401: 402: 403:
404: public function deleteFile($sFirstFile = '') {
405:
406: $sDir = $this->getFilePath();
407:
408: $bDelete = true;
409: if (is_dir($sDir) and $sFirstFile == '') {
410: if (false !== ($handle = cDirHandler::read($sDir))) {
411: foreach ($handle as $sFile) {
412: if (false === cFileHandler::fileNameIsDot($sFile)) {
413:
414: if (false === cFileHandler::remove($sDir . $sFile)) {
415: $bDelete = false;
416: }
417: }
418: }
419:
420: if (true === $bDelete) {
421: $bDelete = cDirHandler::remove($sDir);
422: }
423: }
424: } else if ($sFirstFile != '') {
425: $bDelete = cFileHandler::remove($sDir . $sFirstFile);
426: }
427: if ($bDelete) {
428: return true;
429: } else {
430: return false;
431: }
432: }
433:
434: 435: 436: 437: 438: 439:
440: public function getFilePath() {
441: if ($this->sAlternativePath == '') {
442: $sFrontEndPath = $this->aCfgClient[$this->iClient]['version']['path'];
443: } else {
444: $sFrontEndPath = $this->sAlternativePath . '/' . $this->iClient . '/';
445: }
446: return $sFrontEndPath . $this->sType . '/' . $this->iIdentity . '/';
447: }
448:
449: 450: 451: 452: 453: 454:
455: public function getLastRevision() {
456: return reset($this->aRevisionFiles);
457: }
458:
459: 460: 461: 462: 463: 464:
465: private function getRevision() {
466: $this->iVersion = ($this->iRevisionNumber + 1) . '_' . $this->dActualTimestamp;
467: return $this->iVersion;
468: }
469:
470: 471: 472: 473: 474: 475:
476: protected function getFirstRevision() {
477: $this->initRevisions();
478: $aKey = $this->aRevisionFiles;
479: $sFirstRevision = '';
480:
481:
482: ksort($aKey);
483: foreach ($aKey as $value) {
484: return $sFirstRevision = $value;
485: }
486: return $sFirstRevision;
487: }
488:
489: 490: 491: 492: 493: 494:
495: public function getRevisionFiles() {
496: return $this->aRevisionFiles;
497: }
498:
499: 500: 501: 502: 503: 504:
505: public function getFormatTimestamp() {
506: $aTimes = array();
507: if (count($this->dTimestamp) > 0) {
508: krsort($this->dTimestamp);
509: foreach ($this->dTimestamp as $iKey => $sTimeValue) {
510: $aTimes[$this->aRevisionFiles[$iKey]] = date('d.m.Y H:i:s', $sTimeValue) . ' - Revision: ' . $iKey;
511: }
512: }
513:
514: return $aTimes;
515: }
516:
517: 518: 519: 520: 521: 522: 523: 524:
525: public function setVarForm($sKey, $sValue) {
526: $this->aVarForm[$sKey] = $sValue;
527: }
528:
529: 530: 531: 532: 533: 534: 535: 536: 537: 538: 539: 540: 541: 542: 543: 544: 545:
546: public function buildSelectBox($sTableForm, $sAddHeader, $sLabelOfSelectBox, $sIdOfSelectBox, $disabled = false) {
547: $oForm = new cGuiTableForm($sTableForm);
548:
549:
550: if (count($this->dTimestamp) > 0) {
551:
552: foreach ($this->aVarForm as $sKey => $sValue) {
553: $oForm->setVar($sKey, $sValue);
554: }
555: $aMessage = $this->getMessages();
556: $oForm->addHeader(i18n($sAddHeader));
557: $oForm->add(i18n($sLabelOfSelectBox), $this->getSelectBox($this->getFormatTimestamp(), $sIdOfSelectBox));
558: $oForm->setActionButton('clearhistory', 'images/delete' . (($disabled) ? '_inact' : '') . '.gif', $aMessage['alt'], 'c', 'history_truncate');
559: if(!$disabled) {
560: $oForm->setConfirm('clearhistory', $aMessage['alt'], $aMessage['popup']);
561: }
562: $oForm->setActionButton('submit', 'images/but_refresh.gif', i18n('Refresh'), 's');
563: $oForm->setTableID("version_selector");
564:
565: return $oForm->render();
566: } else {
567: return '';
568: }
569: }
570:
571: 572: 573: 574: 575: 576: 577:
578: private function getMessages() {
579: $aMessage = array();
580: switch ($this->sType) {
581: case 'layout':
582: $aMessage['alt'] = i18n('Clear layout history');
583: $aMessage['popup'] = i18n('Do you really want to clear layout history?') . '<br><br>' . i18n('Note: This only affects the current layout.');
584: break;
585: case 'module':
586: $aMessage['alt'] = i18n('Clear module history');
587: $aMessage['popup'] = i18n('Do you really want to clear module history?') . '<br><br>' . i18n('Note: This only affects the current module.');
588: break;
589: case 'css':
590: $aMessage['alt'] = i18n('Clear style history');
591: $aMessage['popup'] = i18n('Do you really want to clear style history?') . '<br><br>' . i18n('Note: This only affects the current style.');
592: break;
593: case 'js':
594: $aMessage['alt'] = i18n('Clear Java-Script history');
595: $aMessage['popup'] = i18n('Do you really want to clear Java-Script history?') . '<br><br>' . i18n('Note: This only affects the current JavaScript.');
596: break;
597: case 'templates':
598: $aMessage['alt'] = i18n('Clear HTML template history');
599: $aMessage['popup'] = i18n('Do you really want to clear HTML template history?') . '<br><br>' . i18n('Note: This only the affects current HTML template.');
600: break;
601: default:
602: $aMessage['alt'] = i18n('Clear history');
603: $aMessage['popup'] = i18n('Do you really want to clear history?') . '<br><br>' . i18n('Note: This only affects the current history.');
604: break;
605: }
606: return $aMessage;
607: }
608:
609: 610: 611: 612: 613: 614: 615: 616: 617: 618:
619: private function getSelectBox($aTempVesions, $sIdOfSelectBox) {
620: $sSelected = $_POST[$sIdOfSelectBox];
621: $oSelectMenue = new cHTMLSelectElement($sIdOfSelectBox);
622: $oSelectMenue->autoFill($aTempVesions);
623:
624: if ($sSelected != '') {
625: $oSelectMenue->setDefault($sSelected);
626: }
627:
628: return $oSelectMenue->render();
629: }
630:
631: 632: 633: 634: 635: 636: 637: 638: 639: 640: 641: 642: 643: 644: 645: 646: 647:
648: public function getTextarea($sName, $sInitValue, $iWidth, $iHeight, $sId = '', $disabled = false) {
649: if ($sId != '') {
650: $oHTMLTextarea = new cHTMLTextarea($sName, $sInitValue, $iWidth, $iHeight, $sId);
651: } else {
652: $oHTMLTextarea = new cHTMLTextarea($sName, $sInitValue, $iWidth, $iHeight);
653: }
654:
655: if ($disabled) {
656: $oHTMLTextarea->setDisabled('disabled');
657: }
658:
659: $oHTMLTextarea->setStyle('font-family: monospace; width: 100%;');
660: $oHTMLTextarea->updateAttributes(array(
661: 'wrap' => 'off'
662: ));
663:
664: return $oHTMLTextarea->render();
665: }
666:
667: 668: 669: 670: 671: 672: 673: 674: 675: 676: 677: 678: 679: 680:
681: public function getTextBox($sName, $sInitValue, $iWidth, $bDisabled = false) {
682: $oHTMLTextbox = new cHTMLTextbox($sName, conHtmlEntityDecode($sInitValue), $iWidth, '', '', $bDisabled);
683: $oHTMLTextbox->setStyle('font-family:monospace; width:100%;');
684: $oHTMLTextbox->updateAttributes(array(
685: 'wrap' => 'off'
686: ));
687:
688: return $oHTMLTextbox->render();
689: }
690:
691: 692: 693: 694: 695:
696: public function displayNotification($sOutPut) {
697: if ($sOutPut != '') {
698: print $sOutPut;
699: }
700: }
701:
702: 703: 704: 705: 706: 707:
708: public function setBodyNodeDescription($sDesc) {
709: if ($sDesc != '') {
710: $this->sDescripion = conHtmlentities($sDesc);
711: $this->setData('description', $this->sDescripion);
712: }
713: }
714:
715: }
716: