Overview

Packages

  • Core
    • Authentication
    • Backend
    • Cache
    • CEC
    • Chain
    • ContentType
    • Database
    • Datatype
    • Debug
    • Exception
    • Frontend
      • Search
      • URI
      • Util
    • GenericDB
      • Model
    • GUI
      • HTML
    • I18N
    • LayoutHandler
    • Log
    • Security
    • Session
    • Util
    • Validation
    • Versioning
    • XML
  • Module
    • ContentSitemapHtml
    • ContentSitemapXml
    • ContentUserForum
    • NavigationTop
  • mpAutoloaderClassMap
  • None
  • Plugin
    • ContentAllocation
    • CronjobOverview
    • FormAssistant
    • FrontendLogic
    • FrontendUsers
    • Linkchecker
    • ModRewrite
    • Newsletter
    • Repository
      • FrontendNavigation
      • KeywordDensity
    • SearchSolr
    • SmartyWrapper
    • UrlShortener
    • UserForum
    • Workflow
  • PluginManager
  • Setup
    • Form
    • GUI
    • Helper
      • Environment
      • Filesystem
      • MySQL
      • PHP
    • UpgradeJob

Classes

  • cVersion
  • cVersionFile
  • cVersionLayout
  • cVersionModule
  • Overview
  • Package
  • Class
  • Tree
  • Deprecated
  • Todo
  1: <?php
  2: /**
  3:  * This file contains the base version class.
  4:  *
  5:  * @package    Core
  6:  * @subpackage Versioning
  7:  * @version    SVN Revision $Rev:$
  8:  *
  9:  * @author     Bilal Arslan, Timo Trautmann
 10:  * @copyright  four for business AG <www.4fb.de>
 11:  * @license    http://www.contenido.org/license/LIZENZ.txt
 12:  * @link       http://www.4fb.de
 13:  * @link       http://www.contenido.org
 14:  */
 15: 
 16: defined('CON_FRAMEWORK') || die('Illegal call: Missing framework initialization - request aborted.');
 17: 
 18: /**
 19:  * Base version class
 20:  *
 21:  * @package    Core
 22:  * @subpackage Versioning
 23:  */
 24: class cVersion {
 25: 
 26:     /**
 27:      * Id of Type
 28:      *
 29:      * @var string
 30:      */
 31:     protected $sType;
 32: 
 33:     /**
 34:      * md5 coded name of author
 35:      *
 36:      * @var string
 37:      */
 38:     protected $sAuthor;
 39: 
 40:     /**
 41:      * Time of created
 42:      *
 43:      * @var ???
 44:      */
 45:     protected $dCreated;
 46: 
 47:     /**
 48:      * Time of last modified
 49:      *
 50:      * @var ???
 51:      */
 52:     protected $dLastModified;
 53: 
 54:     /**
 55:      * Body data of xml file
 56:      *
 57:      * @var string
 58:      */
 59:     protected $aBodyData;
 60: 
 61:     /**
 62:      * For init global variable
 63:      *
 64:      * @var array
 65:      */
 66:     protected $aCfg;
 67: 
 68:     /**
 69:      * For init global variable $cfgClient
 70:      *
 71:      * @var array
 72:      */
 73:     protected $aCfgClient;
 74: 
 75:     /**
 76:      * Database object
 77:      *
 78:      * @var cDb
 79:      */
 80:     protected $oDB;
 81: 
 82:     /**
 83:      * For init global variable $client
 84:      *
 85:      * @var int
 86:      */
 87:     protected $iClient;
 88: 
 89:     /**
 90:      * Revision files of current file
 91:      *
 92:      * @var array
 93:      */
 94:     public $aRevisionFiles;
 95: 
 96:     /**
 97:      * Number of Revision
 98:      *
 99:      * @var int
100:      */
101:     protected $iRevisionNumber;
102: 
103:     /**
104:      * Timestamp
105:      *
106:      * @var ???
107:      */
108:     protected $dTimestamp;
109: 
110:     /**
111:      * For init global variable $area
112:      *
113:      * @var array
114:      */
115:     protected $sArea;
116: 
117:     /**
118:      * For init global variable $frame
119:      *
120:      * @var int
121:      */
122:     protected $iFrame;
123: 
124:     /**
125:      * For init variables
126:      *
127:      * @var array
128:      */
129:     protected $aVarForm;
130: 
131:     /**
132:      * Identity the Id of Content Type
133:      *
134:      * @var int
135:      */
136:     protected $iIdentity;
137: 
138:     /**
139:      * To take control versioning is switched off
140:      *
141:      * @var bool
142:      */
143:     private $bVersioningActive;
144: 
145:     /**
146:      * Timestamp
147:      *
148:      * @var ???
149:      */
150:     protected $dActualTimestamp;
151: 
152:     /**
153:      * Alternative Path for save version files
154:      *
155:      * @var string
156:      */
157:     protected $sAlternativePath;
158: 
159:     /**
160:      * Displays Notification only onetimes per object
161:      *
162:      * @var int
163:      */
164:     public static $iDisplayNotification;
165: 
166:     /**
167:      * The Version object constructor, initializes class variables
168:      *
169:      * @param array $aCfg
170:      * @param array $aCfgClient
171:      * @param object $oDB
172:      * @param int $iClient
173:      * @param object $sArea
174:      * @param object $iFrame
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:         // Look if versioning is allowed, default is false
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:             // Alternative Path is not true or is not exist, we use the
216:             // frontendpath
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:         // Look if versioning is set alternative path to save
227:         $this->checkPaths();
228:     }
229: 
230:     /**
231:      * This function looks if maximum number of stored versions is achieved.
232:      * If true, it will be delete the first version.
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:      * This function checks if needed version paths exists and were created if
253:      * necessary
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:      * This function initialize the body node of xml file
281:      *
282:      * @param string $sKey
283:      * @param string $sValue
284:      *
285:      * @return array returns an array for body node
286:      */
287:     public function setData($sKey, $sValue) {
288:         $this->aBodyData[$sKey] = $sValue;
289:     }
290: 
291:     /**
292:      * This function creats an xml file.
293:      * XML Writer helps for create this file.
294:      *
295:      * @param string $sFileName name of xml file to create
296:      * @return bool true if saving file was successful, otherwise false
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:      * This function creates new version in right folder.
323:      *
324:      * @return boolean
325:      */
326:     public function createNewVersion() {
327:         if ($this->bVersioningActive == false) {
328:             return false;
329:         }
330: 
331:         // get version name
332:         $sRevisionName = $this->getRevision();
333: 
334:         if (!is_dir($this->getFilePath())) {
335:             mkdir($this->getFilePath(), 0777);
336:             @chmod($this->getFilePath(), 0777);
337:         }
338: 
339:         // Create xml version file
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:      * This function inits version files.
351:      * Its filter also timestamp and version files
352:      *
353:      * @return array returns xml file names
354:      */
355:     protected function initRevisions() {
356:         $this->aRevisionFiles = array();
357:         $this->dTimestamp = array();
358:         // Open this Filepath and read then the content.
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:      * This function deletes files and the the folder, for given path.
382:      *
383:      * @return bool return true if successful
384:      */
385:     public function deleteFile($sFirstFile = '') {
386:         // Open this Filepath and read then the content.
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:                         // Delete the files
395:                         $bDelete = unlink($sDir . $sFile);
396:                     }
397:                 }
398:                 // if the files be cleared, the delete the folder
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:      * Get the frontendpath to revision
413:      *
414:      * @return string returns path to revision file
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:      * Get the last revision file
427:      *
428:      * @return array returns Last Revision
429:      */
430:     public function getLastRevision() {
431:         return reset($this->aRevisionFiles);
432:     }
433: 
434:     /**
435:      * Makes new and init Revision Name
436:      *
437:      * @return int returns number of Revison File
438:      */
439:     private function getRevision() {
440:         $this->iVersion = ($this->iRevisionNumber + 1) . '_' . $this->dActualTimestamp;
441:         return $this->iVersion;
442:     }
443: 
444:     /**
445:      * Inits the first element of revision files
446:      *
447:      * @return string the name of xml files
448:      */
449:     protected function getFirstRevision() {
450:         $this->initRevisions();
451:         $aKey = $this->aRevisionFiles;
452:         $sFirstRevision = '';
453: 
454:         // to take first element, we use right sort
455:         ksort($aKey);
456:         foreach ($aKey as $value) {
457:             return $sFirstRevision = $value;
458:         }
459:         return $sFirstRevision;
460:     }
461: 
462:     /**
463:      * Revision Files
464:      *
465:      * @return array returns all Revison File
466:      */
467:     public function getRevisionFiles() {
468:         return $this->aRevisionFiles;
469:     }
470: 
471:     /**
472:      * This function generate version names for select-box
473:      *
474:      * @return array returns an array of revision file names
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:      * This function generate version names for select-box
490:      *
491:      * @return array returns an array of revision file names
492:      */
493:     public function setVarForm($sKey, $sValue) {
494:         $this->aVarForm[$sKey] = $sValue;
495:     }
496: 
497:     /**
498:      * The general SelectBox function for get Revision.
499:      *
500:      * @param string $sTableForm The name of Table_Form class
501:      * @param string $sAddHeader The Header Label of SelectBox Widget
502:      * @param string $sLabelOfSelectBox The Label of SelectBox Widget
503:      * @param string $sIdOfSelectBox Id of Select Box
504:      *        return string if is exists Revision, then returns HTML Code of
505:      *            full SelectBox else returns empty string
506:      */
507:     public function buildSelectBox($sTableForm, $sAddHeader, $sLabelOfSelectBox, $sIdOfSelectBox) {
508:         $oForm = new cGuiTableForm($sTableForm);
509: 
510:         // if exists xml files
511:         if (count($this->dTimestamp) > 0) {
512: 
513:             foreach ($this->aVarForm as $sKey => $sValue) {
514:                 $oForm->setVar($sKey, $sValue);
515:             }
516:             $aMessage = $this->getMessages();
517:             $oForm->addHeader(i18n($sAddHeader));
518:             $oForm->add(i18n($sLabelOfSelectBox), $this->getSelectBox($this->getFormatTimestamp(), $sIdOfSelectBox));
519:             $oForm->setActionButton('clearhistory', 'images/but_delete.gif', $aMessage['alt'], 'c', 'history_truncate');
520:             $oForm->setConfirm('clearhistory', $aMessage['alt'], $aMessage['popup']);
521:             $oForm->setActionButton('submit', 'images/but_refresh.gif', i18n('Refresh'), 's');
522:             $oForm->setTableid("version_selector");
523: 
524:             return $oForm->render();
525:         } else {
526:             return '';
527:         }
528:     }
529: 
530:     /**
531:      * Messagebox for build selectBox.
532:      * Dynamic allocation for type.
533:      * return array the attributes alt and poput returns
534:      */
535:     private function getMessages() {
536:         $aMessage = array();
537:         switch ($this->sType) {
538:             case 'layout':
539:                 $aMessage['alt'] = i18n('Clear layout history');
540:                 $aMessage['popup'] = i18n('Do you really want to clear layout history?') . '<br><br>' . i18n('Note: This only affects the current layout.');
541:                 break;
542:             case 'module':
543:                 $aMessage['alt'] = i18n('Clear module history');
544:                 $aMessage['popup'] = i18n('Do you really want to clear module history?') . '<br><br>' . i18n('Note: This only affects the current module.');
545:                 break;
546:             case 'css':
547:                 $aMessage['alt'] = i18n('Clear style history');
548:                 $aMessage['popup'] = i18n('Do you really want to clear style history?') . '<br><br>' . i18n('Note: This only affects the current style.');
549:                 break;
550:             case 'js':
551:                 $aMessage['alt'] = i18n('Clear Java-Script history');
552:                 $aMessage['popup'] = i18n('Do you really want to clear Java-Script history?') . '<br><br>' . i18n('Note: This only affects the current JavaScript.');
553:                 break;
554:             case 'templates':
555:                 $aMessage['alt'] = i18n('Clear HTML template history');
556:                 $aMessage['popup'] = i18n('Do you really want to clear HTML template history?') . '<br><br>' . i18n('Note: This only the affects current HTML template.');
557:                 break;
558:             default:
559:                 $aMessage['alt'] = i18n('Clear history');
560:                 $aMessage['popup'] = i18n('Do you really want to clear history?') . '<br><br>' . i18n('Note: This only affects the current history.');
561:                 break;
562:         }
563:         return $aMessage;
564:     }
565: 
566:     /**
567:      * A Class Function for fill version files
568:      *
569:      * @param string $sTableForm The name of Table_Form class
570:      * @param string $sAddHeader The Header Label of SelectBox Widget
571:      *        return string returns select-box with filled files
572:      */
573:     private function getSelectBox($aTempVesions, $sIdOfSelectBox) {
574:         $sSelected = $_POST[$sIdOfSelectBox];
575:         $oSelectMenue = new cHTMLSelectElement($sIdOfSelectBox);
576:         $oSelectMenue->autoFill($aTempVesions);
577: 
578:         if ($sSelected != '') {
579:             $oSelectMenue->setDefault($sSelected);
580:         }
581: 
582:         return $oSelectMenue->render();
583:     }
584: 
585:     /**
586:      * Build new Textarea with below parameters
587:      *
588:      * @param string $sName The name of Textarea.
589:      * @param string $sValue The value of Input Textarea
590:      * @param int $iWidth width of Textarea
591:      * @param int $iHeight height of Textarea
592:      * @return string HTML Code of Textarea
593:      */
594:     public function getTextarea($sName, $sInitValue, $iWidth, $iHeight, $sId = '') {
595:         if ($sId != '') {
596:             $oHTMLTextarea = new cHTMLTextarea($sName, $sInitValue, $iWidth, $iHeight, $sId);
597:         } else {
598:             $oHTMLTextarea = new cHTMLTextarea($sName, $sInitValue, $iWidth, $iHeight);
599:         }
600: 
601:         $oHTMLTextarea->setStyle('font-family: monospace; width: 100%;');
602:         $oHTMLTextarea->updateAttributes(array(
603:             'wrap' => 'off'
604:         ));
605: 
606:         return $oHTMLTextarea->render();
607:     }
608: 
609:     /**
610:      * Build new Textfield with below parameters
611:      *
612:      * @param string $sName The name of Input Textfield.
613:      * @param string $sValue The value of Input Textfield
614:      * @param int $iWidth width of Input Textfield
615:      * @return string HTML Code of Input Textfield
616:      */
617:     public function getTextBox($sName, $sInitValue, $iWidth, $bDisabled = false) {
618:         $oHTMLTextbox = new cHTMLTextbox($sName, conHtmlEntityDecode($sInitValue), $iWidth, '', '', $bDisabled);
619:         $oHTMLTextbox->setStyle('font-family:monospace; width:100%;');
620:         $oHTMLTextbox->updateAttributes(array(
621:             'wrap' => 'off'
622:         ));
623: 
624:         return $oHTMLTextbox->render();
625:     }
626: 
627:     /**
628:      * Displays your notification
629:      *
630:      * @param string $sOutPut
631:      */
632:     public function displayNotification($sOutPut) {
633:         if ($sOutPut != '') {
634:             print $sOutPut;
635:         }
636:     }
637: 
638:     /**
639:      * Set new node for xml file of description
640:      *
641:      * @param string $sDesc Content of node
642:      */
643:     public function setBodyNodeDescription($sDesc) {
644:         if ($sDesc != '') {
645:             $this->sDescripion = conHtmlentities($sDesc);
646:             $this->setData('description', $this->sDescripion);
647:         }
648:     }
649: 
650: }
651: 
CMS CONTENIDO 4.9.3 API documentation generated by ApiGen 2.8.0