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