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 (false !== ($handle = cDirHandler::read($sDir))) {
362: foreach ($handle as $file) {
363: if (false === cFileHandler::fileNameIsDot($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: }
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 = true;
390: if (is_dir($sDir) and $sFirstFile == '') {
391: if (false !== ($handle = cDirHandler::read($sDir))) {
392: foreach ($handle as $sFile) {
393: if (false === cFileHandler::fileNameIsDot($sFile)) {
394:
395: if (false === cFileHandler::remove($sDir . $sFile)) {
396: $bDelete = false;
397: }
398: }
399: }
400:
401: if (true === $bDelete) {
402: $bDelete = cDirHandler::remove($sDir);
403: }
404: }
405: } else if ($sFirstFile != '') {
406: $bDelete = cFileHandler::remove($sDir . $sFirstFile);
407: }
408: if ($bDelete) {
409: return true;
410: } else {
411: return false;
412: }
413: }
414:
415: 416: 417: 418: 419:
420: public function getFilePath() {
421: if ($this->sAlternativePath == '') {
422: $sFrontEndPath = $this->aCfgClient[$this->iClient]['version']['path'];
423: } else {
424: $sFrontEndPath = $this->sAlternativePath . '/' . $this->iClient . '/';
425: }
426: return $sFrontEndPath . $this->sType . '/' . $this->iIdentity . '/';
427: }
428:
429: 430: 431: 432: 433:
434: public function getLastRevision() {
435: return reset($this->aRevisionFiles);
436: }
437:
438: 439: 440: 441: 442:
443: private function getRevision() {
444: $this->iVersion = ($this->iRevisionNumber + 1) . '_' . $this->dActualTimestamp;
445: return $this->iVersion;
446: }
447:
448: 449: 450: 451: 452:
453: protected function getFirstRevision() {
454: $this->initRevisions();
455: $aKey = $this->aRevisionFiles;
456: $sFirstRevision = '';
457:
458:
459: ksort($aKey);
460: foreach ($aKey as $value) {
461: return $sFirstRevision = $value;
462: }
463: return $sFirstRevision;
464: }
465:
466: 467: 468: 469: 470:
471: public function getRevisionFiles() {
472: return $this->aRevisionFiles;
473: }
474:
475: 476: 477: 478: 479:
480: public function getFormatTimestamp() {
481: $aTimes = array();
482: if (count($this->dTimestamp) > 0) {
483: krsort($this->dTimestamp);
484: foreach ($this->dTimestamp as $iKey => $sTimeValue) {
485: $aTimes[$this->aRevisionFiles[$iKey]] = date('d.m.Y H:i:s', $sTimeValue) . ' - Revision: ' . $iKey;
486: }
487: }
488:
489: return $aTimes;
490: }
491:
492: 493: 494: 495: 496:
497: public function setVarForm($sKey, $sValue) {
498: $this->aVarForm[$sKey] = $sValue;
499: }
500:
501: 502: 503: 504: 505: 506: 507: 508: 509: 510: 511:
512: public function buildSelectBox($sTableForm, $sAddHeader, $sLabelOfSelectBox, $sIdOfSelectBox, $disabled = false) {
513: $oForm = new cGuiTableForm($sTableForm);
514:
515:
516: if (count($this->dTimestamp) > 0) {
517:
518: foreach ($this->aVarForm as $sKey => $sValue) {
519: $oForm->setVar($sKey, $sValue);
520: }
521: $aMessage = $this->getMessages();
522: $oForm->addHeader(i18n($sAddHeader));
523: $oForm->add(i18n($sLabelOfSelectBox), $this->getSelectBox($this->getFormatTimestamp(), $sIdOfSelectBox));
524: $oForm->setActionButton('clearhistory', 'images/delete' . (($disabled) ? '_inact' : '') . '.gif', $aMessage['alt'], 'c', 'history_truncate');
525: if(!$disabled) {
526: $oForm->setConfirm('clearhistory', $aMessage['alt'], $aMessage['popup']);
527: }
528: $oForm->setActionButton('submit', 'images/but_refresh.gif', i18n('Refresh'), 's');
529: $oForm->setTableid("version_selector");
530:
531: return $oForm->render();
532: } else {
533: return '';
534: }
535: }
536:
537: 538: 539: 540: 541:
542: private function getMessages() {
543: $aMessage = array();
544: switch ($this->sType) {
545: case 'layout':
546: $aMessage['alt'] = i18n('Clear layout history');
547: $aMessage['popup'] = i18n('Do you really want to clear layout history?') . '<br><br>' . i18n('Note: This only affects the current layout.');
548: break;
549: case 'module':
550: $aMessage['alt'] = i18n('Clear module history');
551: $aMessage['popup'] = i18n('Do you really want to clear module history?') . '<br><br>' . i18n('Note: This only affects the current module.');
552: break;
553: case 'css':
554: $aMessage['alt'] = i18n('Clear style history');
555: $aMessage['popup'] = i18n('Do you really want to clear style history?') . '<br><br>' . i18n('Note: This only affects the current style.');
556: break;
557: case 'js':
558: $aMessage['alt'] = i18n('Clear Java-Script history');
559: $aMessage['popup'] = i18n('Do you really want to clear Java-Script history?') . '<br><br>' . i18n('Note: This only affects the current JavaScript.');
560: break;
561: case 'templates':
562: $aMessage['alt'] = i18n('Clear HTML template history');
563: $aMessage['popup'] = i18n('Do you really want to clear HTML template history?') . '<br><br>' . i18n('Note: This only the affects current HTML template.');
564: break;
565: default:
566: $aMessage['alt'] = i18n('Clear history');
567: $aMessage['popup'] = i18n('Do you really want to clear history?') . '<br><br>' . i18n('Note: This only affects the current history.');
568: break;
569: }
570: return $aMessage;
571: }
572:
573: 574: 575: 576: 577: 578: 579:
580: private function getSelectBox($aTempVesions, $sIdOfSelectBox) {
581: $sSelected = $_POST[$sIdOfSelectBox];
582: $oSelectMenue = new cHTMLSelectElement($sIdOfSelectBox);
583: $oSelectMenue->autoFill($aTempVesions);
584:
585: if ($sSelected != '') {
586: $oSelectMenue->setDefault($sSelected);
587: }
588:
589: return $oSelectMenue->render();
590: }
591:
592: 593: 594: 595: 596: 597: 598: 599: 600: 601:
602: public function getTextarea($sName, $sInitValue, $iWidth, $iHeight, $sId = '', $disabled = false) {
603: if ($sId != '') {
604: $oHTMLTextarea = new cHTMLTextarea($sName, $sInitValue, $iWidth, $iHeight, $sId);
605: } else {
606: $oHTMLTextarea = new cHTMLTextarea($sName, $sInitValue, $iWidth, $iHeight);
607: }
608:
609: if($disabled) {
610: $oHTMLTextarea->setDisabled('disabled');
611: }
612:
613: $oHTMLTextarea->setStyle('font-family: monospace; width: 100%;');
614: $oHTMLTextarea->updateAttributes(array(
615: 'wrap' => 'off'
616: ));
617:
618: return $oHTMLTextarea->render();
619: }
620:
621: 622: 623: 624: 625: 626: 627: 628:
629: public function getTextBox($sName, $sInitValue, $iWidth, $bDisabled = false) {
630: $oHTMLTextbox = new cHTMLTextbox($sName, conHtmlEntityDecode($sInitValue), $iWidth, '', '', $bDisabled);
631: $oHTMLTextbox->setStyle('font-family:monospace; width:100%;');
632: $oHTMLTextbox->updateAttributes(array(
633: 'wrap' => 'off'
634: ));
635:
636: return $oHTMLTextbox->render();
637: }
638:
639: 640: 641: 642: 643:
644: public function displayNotification($sOutPut) {
645: if ($sOutPut != '') {
646: print $sOutPut;
647: }
648: }
649:
650: 651: 652: 653: 654:
655: public function setBodyNodeDescription($sDesc) {
656: if ($sDesc != '') {
657: $this->sDescripion = conHtmlentities($sDesc);
658: $this->setData('description', $this->sDescripion);
659: }
660: }
661:
662: }
663: