Overview

Packages

  • CONTENIDO
  • Core
    • Authentication
    • Backend
    • Cache
    • CEC
    • Chain
    • ContentType
    • Database
    • Debug
    • Exception
    • Frontend
      • Search
      • URI
      • Util
    • GenericDB
      • Model
    • GUI
      • HTML
    • I18N
    • LayoutHandler
    • Log
    • Security
    • Session
    • Util
    • Validation
    • Versioning
    • XML
  • Module
    • ContentRssCreator
    • ContentSitemapHtml
    • ContentSitemapXml
    • ContentUserForum
    • NavigationTop
    • ScriptCookieDirective
  • 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

  • cContentVersioning
  • cVersion
  • cVersionFile
  • cVersionLayout
  • cVersionModule
  • Overview
  • Package
  • Class
  • Tree
  • Deprecated
  • Todo
  1: <?php
  2: 
  3: /**
  4:  * This file contains the base version class.
  5:  *
  6:  * @package    Core
  7:  * @subpackage Versioning
  8:  * @version    SVN Revision $Rev:$
  9:  *
 10:  * @author     Bilal Arslan, Timo Trautmann
 11:  * @copyright  four for business AG <www.4fb.de>
 12:  * @license    http://www.contenido.org/license/LIZENZ.txt
 13:  * @link       http://www.4fb.de
 14:  * @link       http://www.contenido.org
 15:  */
 16: 
 17: defined('CON_FRAMEWORK') || die('Illegal call: Missing framework initialization - request aborted.');
 18: 
 19: /**
 20:  * Base version class
 21:  *
 22:  * @package    Core
 23:  * @subpackage Versioning
 24:  */
 25: class cVersion {
 26: 
 27:     /**
 28:      * Id of Type
 29:      *
 30:      * @var string
 31:      */
 32:     protected $sType;
 33: 
 34:     /**
 35:      * md5 coded name of author
 36:      *
 37:      * @var string
 38:      */
 39:     protected $sAuthor;
 40: 
 41:     /**
 42:      * Time of created
 43:      *
 44:      * @var ???
 45:      */
 46:     protected $dCreated;
 47: 
 48:     /**
 49:      * Time of last modified
 50:      *
 51:      * @var unknown_type
 52:      */
 53:     protected $dLastModified;
 54: 
 55:     /**
 56:      * Body data of xml file
 57:      *
 58:      * @var string
 59:      */
 60:     protected $aBodyData;
 61: 
 62:     /**
 63:      * For init global variable
 64:      *
 65:      * @var array
 66:      */
 67:     protected $aCfg;
 68: 
 69:     /**
 70:      * For init global variable $cfgClient
 71:      *
 72:      * @var array
 73:      */
 74:     protected $aCfgClient;
 75: 
 76:     /**
 77:      * Database object
 78:      *
 79:      * @var cDb
 80:      */
 81:     protected $oDB;
 82: 
 83:     /**
 84:      * For init global variable $client
 85:      *
 86:      * @var int
 87:      */
 88:     protected $iClient;
 89: 
 90:     /**
 91:      * Revision files of current file
 92:      *
 93:      * @var array
 94:      */
 95:     public $aRevisionFiles;
 96: 
 97:     /**
 98:      * Number of Revision
 99:      *
100:      * @var int
101:      */
102:     protected $iRevisionNumber;
103: 
104:     /**
105:      * Timestamp
106:      *
107:      * @var unknown_type
108:      */
109:     protected $dTimestamp;
110: 
111:     /**
112:      * For init global variable $area
113:      *
114:      * @var array
115:      */
116:     protected $sArea;
117: 
118:     /**
119:      * For init global variable $frame
120:      *
121:      * @var int
122:      */
123:     protected $iFrame;
124: 
125:     /**
126:      * For init variables
127:      *
128:      * @var array
129:      */
130:     protected $aVarForm;
131: 
132:     /**
133:      * Identity the Id of Content Type
134:      *
135:      * @var int
136:      */
137:     protected $iIdentity;
138: 
139:     /**
140:      * To take control versioning is switched off
141:      *
142:      * @var bool
143:      */
144:     private $bVersioningActive;
145: 
146:     /**
147:      * Timestamp
148:      *
149:      * @var unknown_type
150:      */
151:     protected $dActualTimestamp;
152: 
153:     /**
154:      * Alternative Path for save version files
155:      *
156:      * @var string
157:      */
158:     protected $sAlternativePath;
159: 
160:     /**
161:      * Displays Notification only onetimes per object
162:      *
163:      * @var int
164:      */
165:     public static $iDisplayNotification;
166: 
167:     /**
168:      * The Version object constructor, initializes class variables
169:      *
170:      * @param array $aCfg
171:      * @param array $aCfgClient
172:      * @param object $oDB
173:      * @param int $iClient
174:      * @param object $sArea
175:      * @param object $iFrame
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:         // Look if versioning is allowed, default is false
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:             // Alternative Path is not true or is not exist, we use the
217:             // frontendpath
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:         // Look if versioning is set alternative path to save
228:         $this->checkPaths();
229:     }
230: 
231:     /**
232:      * This function looks if maximum number of stored versions is achieved.
233:      * If true, it will be delete the first version.
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:      * This function checks if needed version paths exists and were created if
254:      * necessary
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:      * This function initialize the body node of xml file
282:      *
283:      * @param string $sKey
284:      * @param string $sValue
285:      * @return array
286:      *         returns an array for body node
287:      */
288:     public function setData($sKey, $sValue) {
289:         $this->aBodyData[$sKey] = $sValue;
290:     }
291: 
292:     /**
293:      * This function creats an xml file.
294:      * XML Writer helps for create this file.
295:      *
296:      * @param string $sDirectory
297:      * @param string $sFileName
298:      *         name of xml file to create
299:      * @return bool
300:      *         true if saving file was successful, otherwise false
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:      * This function creates new version in right folder.
327:      *
328:      * @throws cException
329:      *         if new version could not be created
330:      * @return bool
331:      */
332:     public function createNewVersion() {
333:         if ($this->bVersioningActive == false) {
334:             return false;
335:         }
336: 
337:         // get version name
338:         $sRevisionName = $this->getRevision();
339: 
340:         if (!is_dir($this->getFilePath())) {
341:             mkdir($this->getFilePath(), 0777);
342:             @chmod($this->getFilePath(), 0777);
343:         }
344: 
345:         // Create xml version file
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:      * This function inits version files.
357:      * Its filter also timestamp and version files
358:      *
359:      * @return array
360:      *         returns xml file names
361:      */
362:     protected function initRevisions() {
363:         $this->aRevisionFiles = array();
364:         $this->dTimestamp = array();
365:         // Open this Filepath and read then the content.
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:      * This function deletes files and the the folder, for given path.
389:      *
390:      * @param string $sFirstFile [optional]
391:      * @return bool
392:      *         return true if successful
393:      */
394:     public function deleteFile($sFirstFile = '') {
395:         // Open this Filepath and read then the content.
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:                         // Delete the files
404:                         if (false === cFileHandler::remove($sDir . $sFile)) {
405:                             $bDelete = false;
406:                         }
407:                     }
408:                 }
409:                 // if the files be cleared, the delete the folder
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:      * Get the frontendpath to revision
426:      *
427:      * @return string
428:      *         returns path to revision file
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:      * Get the last revision file
441:      *
442:      * @return array
443:      *         returns Last Revision
444:      */
445:     public function getLastRevision() {
446:         return reset($this->aRevisionFiles);
447:     }
448: 
449:     /**
450:      * Makes new and init Revision Name
451:      *
452:      * @return int
453:      *         returns number of Revison File
454:      */
455:     private function getRevision() {
456:         $this->iVersion = ($this->iRevisionNumber + 1) . '_' . $this->dActualTimestamp;
457:         return $this->iVersion;
458:     }
459: 
460:     /**
461:      * Inits the first element of revision files
462:      *
463:      * @return string
464:      *         the name of xml files
465:      */
466:     protected function getFirstRevision() {
467:         $this->initRevisions();
468:         $aKey = $this->aRevisionFiles;
469:         $sFirstRevision = '';
470: 
471:         // to take first element, we use right sort
472:         ksort($aKey);
473:         foreach ($aKey as $value) {
474:             return $sFirstRevision = $value;
475:         }
476:         return $sFirstRevision;
477:     }
478: 
479:     /**
480:      * Revision Files
481:      *
482:      * @return array
483:      *         returns all Revison File
484:      */
485:     public function getRevisionFiles() {
486:         return $this->aRevisionFiles;
487:     }
488: 
489:     /**
490:      * This function generate version names for select-box
491:      *
492:      * @return array
493:      *         returns an array of revision file names
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:      * This function generate version names for select-box
509:      *
510:      * @param string $sKey
511:      * @param string $sValue
512:      * @return array
513:      *         returns an array of revision file names
514:      */
515:     public function setVarForm($sKey, $sValue) {
516:         $this->aVarForm[$sKey] = $sValue;
517:     }
518: 
519:     /**
520:      * The general SelectBox function for get Revision.
521:      *
522:      * @param string $sTableForm
523:      *         The name of Table_Form class
524:      * @param string $sAddHeader
525:      *         The Header Label of SelectBox Widget
526:      * @param string $sLabelOfSelectBox
527:      *         The Label of SelectBox Widget
528:      * @param string $sIdOfSelectBox
529:      *         Id of Select Box
530:      * @param bool $disabled [optional]
531:      *         If true, show disabled buttons for deleting
532:      * @return string
533:      *         if is exists Revision, then returns HTML Code of full SelectBox
534:      *         else returns empty string
535:      */
536:     public function buildSelectBox($sTableForm, $sAddHeader, $sLabelOfSelectBox, $sIdOfSelectBox, $disabled = false) {
537:         $oForm = new cGuiTableForm($sTableForm);
538: 
539:         // if exists xml files
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:      * Messagebox for build selectBox.
563:      * Dynamic allocation for type.
564:      *
565:      * @return array
566:      *         the attributes alt and poput returns
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:      * A Class Function for fill version files
601:      *
602:      * @param string $sTableForm
603:      *         The name of Table_Form class
604:      * @param string $sAddHeader
605:      *         The Header Label of SelectBox Widget
606:      * @return string
607:      *         returns select-box with filled files
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:      * Build new Textarea with below parameters
623:      *
624:      * @param string $sName
625:      *         The name of Textarea.
626:      * @param string $sInitValue
627:      *         The value of Input Textarea
628:      * @param int $iWidth
629:      *         width of Textarea
630:      * @param int $iHeight
631:      *         height of Textarea
632:      * @param string $sId [optional]
633:      * @param bool $disabled [optional]
634:      *         Disabled Textarea
635:      * @return string
636:      *         HTML Code of Textarea
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:      * Build new Textfield with below parameters
659:      *
660:      * @param string $sName
661:      *         The name of Input Textfield.
662:      * @param string $sInitValue
663:      *         The value of Input Textfield
664:      * @param int $iWidth
665:      *         width of Input Textfield
666:      * @param bool $bDisabled [optional]
667:      *         Disabled TextBox
668:      * @return string
669:      *         HTML Code of Input Textfield
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:      * Displays your notification
683:      *
684:      * @param string $sOutPut
685:      */
686:     public function displayNotification($sOutPut) {
687:         if ($sOutPut != '') {
688:             print $sOutPut;
689:         }
690:     }
691: 
692:     /**
693:      * Set new node for xml file of description
694:      *
695:      * @param string $sDesc
696:      *         Content of node
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: 
CMS CONTENIDO 4.9.8 API documentation generated by ApiGen 2.8.0