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