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