diff --git a/application/controllers/admin/templateoptions.php b/application/controllers/admin/templateoptions.php index f792ddcc7bb..b5a9f942749 100644 --- a/application/controllers/admin/templateoptions.php +++ b/application/controllers/admin/templateoptions.php @@ -174,7 +174,10 @@ public function index() $aData = array(); - $model = new TemplateConfiguration('search'); + //$model = new TemplateConfiguration('search'); + $model = new TemplateConfiguration(); + + //$aFtpTemplates = ; $aData['model'] = $model; $this->_renderWrappedTemplate('templateoptions', 'index', $aData); @@ -213,6 +216,19 @@ public function loadModel($id) return $model; } + + public function importManifest($templatename) + { + TemplateManifest::importManifest($templatename); + $this->getController()->redirect(array("admin/templateoptions")); + } + + public function uninstall($templatename) + { + TemplateConfiguration::uninstall($templatename); + $this->getController()->redirect(array("admin/templateoptions")); + } + /** * Performs the AJAX validation. * @param TemplateOptions $model the model to be validated diff --git a/application/models/Template.php b/application/models/Template.php index 3dbd48dd785..4f948c2aa33 100644 --- a/application/models/Template.php +++ b/application/models/Template.php @@ -37,6 +37,8 @@ */ class Template extends LSActiveRecord { + /** @var array $aTemplatesInUploadDir cache for the method getUploadTemplates */ + public static $aTemplatesInUploadDir = null; /** @var Template - The instance of template object */ private static $instance; @@ -215,6 +217,8 @@ public static function getTemplateConfiguration($sTemplateName=null, $iSurveyId= // If no row found, or if the template folder for this configuration row doesn't exist we load the XML config (which will load the default XML) if ( $bForceXML || !is_a($oTemplateConfigurationModel, 'TemplateConfiguration') || ! $oTemplateConfigurationModel->checkTemplate()){ $oTemplateConfigurationModel = new TemplateManifest; + $oTemplateConfigurationModel->setBasics($sTemplateName, $iSurveyId); + } //$oTemplateConfigurationModel->prepareTemplateRendering($sTemplateName, $iSurveyId); @@ -464,6 +468,34 @@ public static function getStandardTemplateList() // return self::$standardTemplates; } + + + + public static function getUploadTemplates() + { + + if(empty(self::$aTemplatesInUploadDir)){ + + $sUserTemplateRootDir = Yii::app()->getConfig("usertemplaterootdir"); + $aTemplateList = array(); + + if ($sUserTemplateRootDir && $handle = opendir($sUserTemplateRootDir)){ + + while (false !== ($sFileName = readdir($handle))){ + + if (!is_file("$sUserTemplateRootDir/$sFileName") && $sFileName != "." && $sFileName != ".." && $sFileName!=".svn" && (file_exists("{$sUserTemplateRootDir}/{$sFileName}/config.xml") )){ + $aTemplateList[$sFileName] = $sUserTemplateRootDir.DIRECTORY_SEPARATOR.$sFileName; + } + } + closedir($handle); + } + ksort($aTemplateList); + self::$aTemplatesInUploadDir = $aTemplateList; + } + + return self::$aTemplatesInUploadDir; + } + /** * Retrieves a list of models based on the current search/filter conditions. * diff --git a/application/models/TemplateConfig.php b/application/models/TemplateConfig.php index bbbf692ad1f..06716d5ee15 100644 --- a/application/models/TemplateConfig.php +++ b/application/models/TemplateConfig.php @@ -784,6 +784,60 @@ public function __toString() return $s; } + + public static function uninstall($templatename ) + { + if (Permission::model()->hasGlobalPermission('templates','delete')) + { + $oTemplate = Template::model()->findByAttributes(array('name' => $templatename)); + if( $oTemplate->delete()){ + $oTemplateConfig = TemplateConfiguration::model()->findByAttributes(array('template_name' => $templatename)); + return TemplateConfiguration::model()->deleteAll('template_name=:templateName', array(':templateName' => $templatename) ); + } + } + return false; + } + + /** + * Create a new entry in {{templates}} and {{template_configuration}} table using the template manifest + * @param string $sTemplateName the name of the template to import + * @return mixed true on success | exception + * @throws Exception + */ + public static function importManifest($sTemplateName, $aDatas ) + { + $oNewTemplate = new Template; + $oNewTemplate->name = $sTemplateName; + $oNewTemplate->folder = $sTemplateName; + $oNewTemplate->title = $sTemplateName; // For now, when created via template editor => name == folder == title + $oNewTemplate->creation_date = date("Y-m-d H:i:s"); + $oNewTemplate->author = Yii::app()->user->name; + $oNewTemplate->author_email = ''; // privacy + $oNewTemplate->author_url = ''; // privacy + $oNewTemplate->api_version = $aDatas['api_version']; + $oNewTemplate->view_folder = $aDatas['view_folder']; + $oNewTemplate->files_folder = $aDatas['files_folder']; + //$oNewTemplate->description TODO: a more complex modal whith email, author, url, licence, desc, etc + $oNewTemplate->owner_id = Yii::app()->user->id; + $oNewTemplate->extends = $aDatas['extends']; + + if ($oNewTemplate->save()){ + $oNewTemplateConfiguration = new TemplateConfiguration; + $oNewTemplateConfiguration->template_name = $sTemplateName; + $oNewTemplateConfiguration->template_name = $sTemplateName; + $oNewTemplateConfiguration->options = json_encode($aDatas['aOptions']); + + + if ($oNewTemplateConfiguration->save()){ + return true; + }else{ + throw new Exception($oNewTemplateConfiguration->getErrors()); + } + }else{ + throw new Exception($oNewTemplate->getErrors()); + } + } + // TODO: try to refactore most of those methods in TemplateConfiguration and TemplateManifest so we can define their body here. // It will consist in adding private methods to get the values of variables... See what has been done for createTemplatePackage // Then, the lonely differences between TemplateManifest and TemplateConfiguration should be how to retreive and format the data diff --git a/application/models/TemplateConfiguration.php b/application/models/TemplateConfiguration.php index 13dff34d893..62ada3d4d65 100644 --- a/application/models/TemplateConfiguration.php +++ b/application/models/TemplateConfiguration.php @@ -54,6 +54,8 @@ class TemplateConfiguration extends TemplateConfig // Caches + public $allDbTemplateFolders = null; + /** @var string $sPreviewImgTag the template preview image tag for the template list*/ public $sPreviewImgTag; @@ -308,42 +310,23 @@ public function getPreview() * @return mixed true on success | exception * @throws Exception */ - public static function importManifest($sTemplateName) + public static function importManifest($sTemplateName, $aDatas=array() ) { - $oEditedTemplate = Template::model()->getTemplateConfiguration($sTemplateName, null,null, false); - $oEditedTemplate->prepareTemplateRendering($sTemplateName); - - $oEditTemplateDb = Template::model()->findByPk($oEditedTemplate->oMotherTemplate->sTemplateName); - $oNewTemplate = new Template; - $oNewTemplate->name = $oEditedTemplate->sTemplateName; - $oNewTemplate->folder = $oEditedTemplate->sTemplateName; - $oNewTemplate->title = $oEditedTemplate->sTemplateName; // For now, when created via template editor => name == folder == title - $oNewTemplate->creation_date = date("Y-m-d H:i:s"); - $oNewTemplate->author = Yii::app()->user->name; - $oNewTemplate->author_email = ''; // privacy - $oNewTemplate->author_url = ''; // privacy - $oNewTemplate->api_version = $oEditTemplateDb->api_version; - $oNewTemplate->view_folder = $oEditTemplateDb->view_folder; - $oNewTemplate->files_folder = $oEditTemplateDb->files_folder; - //$oNewTemplate->description TODO: a more complex modal whith email, author, url, licence, desc, etc - $oNewTemplate->owner_id = Yii::app()->user->id; - $oNewTemplate->extends = $oEditedTemplate->oMotherTemplate->sTemplateName; - - if ($oNewTemplate->save()){ - $oNewTemplateConfiguration = new TemplateConfiguration; - $oNewTemplateConfiguration->template_name = $oEditedTemplate->sTemplateName; - $oNewTemplateConfiguration->template_name = $oEditedTemplate->sTemplateName; - $oNewTemplateConfiguration->options = json_encode($oEditedTemplate->oOptions); - - - if ($oNewTemplateConfiguration->save()){ - return true; - }else{ - throw new Exception($oNewTemplateConfiguration->getErrors()); - } - }else{ - throw new Exception($oNewTemplate->getErrors()); + if ( !empty($aDatas['extends']) ){ + + $oEditTemplateDb = Template::model()->findByPk($aDatas['extends']); + + $aDatas['api_version'] = $oEditTemplateDb->api_version; + $aDatas['view_folder'] = $oEditTemplateDb->view_folder; + $aDatas['author_email'] = $oEditTemplateDb->author_email; + $aDatas['author_url'] = $oEditTemplateDb->author_url; + $aDatas['copyright'] = $oEditTemplateDb->copyright; + $aDatas['version'] = $oEditTemplateDb->version; + $aDatas['license'] = $oEditTemplateDb->license; + $aDatas['files_folder'] = $oEditTemplateDb->files_folder; } + + return parent::importManifest($sTemplateName, $aDatas ); } public function setToInherit(){ @@ -382,15 +365,20 @@ public function checkTemplate() public function prepareTemplateRendering($sTemplateName='', $iSurveyId='', $bUseMagicInherit=true) { $this->bUseMagicInherit = $bUseMagicInherit; + $this->setBasics($sTemplateName, $iSurveyId); + $this->setMotherTemplates(); // Recursive mother templates configuration + $this->setThisTemplate(); // Set the main config values of this template + $this->createTemplatePackage($this); // Create an asset package ready to be loaded + return $this; + } + + public function setBasics($sTemplateName='', $iSurveyId='') + { $this->sTemplateName = $this->template->name; $this->setIsStandard(); // Check if it is a CORE template $this->path = ($this->isStandard) ? Yii::app()->getConfig("standardtemplaterootdir").DIRECTORY_SEPARATOR.$this->template->folder : Yii::app()->getConfig("usertemplaterootdir").DIRECTORY_SEPARATOR.$this->template->folder; - $this->setMotherTemplates(); // Recursive mother templates configuration - $this->setThisTemplate(); // Set the main config values of this template - $this->createTemplatePackage($this); // Create an asset package ready to be loaded - return $this; } /** @@ -430,11 +418,12 @@ public function getTypeIcon() public function getButtons() { - $sEditorUrl = Yii::app()->getController()->createUrl('admin/templates/sa/view', array("templatename"=>$this->template->name)); - $sOptionUrl = Yii::app()->getController()->createUrl('admin/templateoptions/sa/update', array("id"=>$this->id)); + $sEditorUrl = Yii::app()->getController()->createUrl('admin/templates/sa/view', array("templatename"=>$this->template_name)); + $sOptionUrl = Yii::app()->getController()->createUrl('admin/templateoptions/sa/update', array("id"=>$this->id)); + $sUninstallUrl = Yii::app()->getController()->createUrl('admin/templateoptions/sa/uninstall/', array("templatename"=>$this->template_name)); $sEditorLink = " @@ -447,7 +436,7 @@ class='btn btn-default'> if ($this->hasOptionPage){ $OptionLink .= " @@ -455,9 +444,22 @@ class='btn btn-default'> "; } + $sUninstallLink = " + + ".gT('Uninstall')." + "; + + $sButtons = $sEditorLink.'

'.$OptionLink; + + if (!$this->isStandard){ + $sButtons .= '

'.$sUninstallLink ; + } - return $sEditorLink.'

'.$OptionLink; + return $sButtons; } public function getHasOptionPage() @@ -518,7 +520,7 @@ protected function getFilesToLoad($oTemplate, $sType) } } } - + return $this->aFilesToLoad[$sType]; } @@ -681,7 +683,7 @@ protected function getFrameworkAssetsToReplace( $sType, $bInlcudeRemove = false) $this->aFrameworkAssetsToReplace[$sType] = array_merge($this->aFrameworkAssetsToReplace, (array) $aFieldValue['remove'] ); } } - + return $this->aFrameworkAssetsToReplace[$sType]; } @@ -705,7 +707,7 @@ protected function getFrameworkAssetsReplacement( $sType ) $aReplace = $aAsset[1]; $this->aReplacements[$sType][] = $aReplace; } - + return $this->aReplacements[$sType]; } @@ -748,6 +750,41 @@ public function getParentConfiguration(){ return $this->oParentTemplate; } + + public function getTemplatesWithNoDb() + { + $aTemplatesInUpload = Template::getUploadTemplates(); + $aTemplatesInDb = $this->getAllDbTemplateFolders(); + $aTemplatesWithoutDB = array(); + + foreach ($aTemplatesInUpload as $sName => $sPath) { + if (! in_array($sName, $aTemplatesInDb) ){ + $aTemplatesWithoutDB[$sName] = Template::getTemplateConfiguration($sName, null, null, true); // Get the manifest + } + } + + return $aTemplatesWithoutDB; + } + + public function getAllDbTemplateFolders() + { + if (empty($this->allDbTemplateFolders)){ + + $oCriteria = new CDbCriteria; + $oCriteria->select = 'folder'; + $oAllDbTemplateFolders = Template::model()->findAll($oCriteria); + + $aAllDbTemplateFolders = array(); + foreach ($oAllDbTemplateFolders as $oAllDbTemplateFolders){ + $aAllDbTemplateFolders[] = $oAllDbTemplateFolders->folder; + } + + $this->allDbTemplateFolders = array_unique($aAllDbTemplateFolders); + } + + return $this->allDbTemplateFolders; + } + /** * Proxy for the AR method to manage the inheritance * If one of the field that can be inherited is set to "inherit", then it will return the value of its parent diff --git a/application/models/TemplateManifest.php b/application/models/TemplateManifest.php index ff32ed87f15..3ec8281341e 100644 --- a/application/models/TemplateManifest.php +++ b/application/models/TemplateManifest.php @@ -24,6 +24,8 @@ class TemplateManifest extends TemplateConfiguration { public $templateEditor; + public $sPreviewImgTag; + /** * Public interface specific to TemplateManifest * They are used in TemplateEditor @@ -210,6 +212,91 @@ public function getOtherFiles() return $otherfiles; } + + public function getPreview() + { + if (empty($this->sPreviewImgTag)){ + $previewUrl = $this->getTemplateURL();// $this->getTemplateURL();//Template::getTemplateURL($this->template->name); + $this->sPreviewImgTag = 'template preview'; + } + return $this->sPreviewImgTag; + } + + /** + * NOTE: a core template will always be in the DB. So this function concerns only uploaded templates + */ + public function getTemplateURL() + { + return Yii::app()->getConfig("usertemplaterooturl").'/'.$this->sTemplateName.'/'; + } + + + public function getButtons() + { + $sEditorUrl = Yii::app()->getController()->createUrl('admin/templates/sa/view', array("templatename"=>$this->sTemplateName)); + $sLoadUrl = Yii::app()->getController()->createUrl('admin/templateoptions/sa/importmanifest/', array("templatename"=>$this->sTemplateName)); + $sDeleteUrl = Yii::app()->getController()->createUrl('admin/templateoptions/sa/deleteTemplate/', array("templatename"=>$this->sTemplateName)); + + // TODO: load to DB + $sEditorLink = " + + ".gT('Template editor')." + "; + + // + + $sLoadLink = ''; + + $sLoadLink .= " + + ".gT('Install')." + "; + + $sDeleteLink = " + + ".gT('Delete')." + "; + + + return $sEditorLink.'

'.$sLoadLink.'

'; //.$sDeleteLink; + } + + /** + * Create a new entry in {{templates}} and {{template_configuration}} table using the template manifest + * @param string $sTemplateName the name of the template to import + * @return mixed true on success | exception + * @throws Exception + */ + public static function importManifest($sTemplateName, $aDatas=array() ) + { + $oTemplate = Template::getTemplateConfiguration($sTemplateName, null, null, true); + + $aDatas['api_version'] = (string) $oTemplate->config->metadatas->apiVersion; + $aDatas['extends'] = (string) $oTemplate->config->metadatas->extends; + $aDatas['author_email'] = (string) $oTemplate->config->metadatas->authorEmail; + $aDatas['author_url'] = (string) $oTemplate->config->metadatas->authorUrl; + $aDatas['copyright'] = (string) $oTemplate->config->metadatas->copyright; + $aDatas['version'] = (string) $oTemplate->config->metadatas->version; + $aDatas['license'] = (string) $oTemplate->config->metadatas->license; + $aDatas['view_folder'] = (string) $oTemplate->config->engine->viewdirectory; + $aDatas['files_folder'] = (string) $oTemplate->config->engine->filesdirectory; + $aDatas['aOptions'] = (!empty($oTemplate->config->options[0]) && count($oTemplate->config->options[0]) == 0 )?array():$oTemplate->config->options[0]; // If template provide empty options, it must be cleaned to avoid crashes + + + return parent::importManifest($sTemplateName, $aDatas ); + } + + + /** * Update the config file of a given template so that it extends another one * @@ -378,16 +465,22 @@ private function setTemplateName($sTemplateName='', $iSurveyId='') */ public function prepareTemplateRendering($sTemplateName='', $iSurveyId='', $bUseMagicInherit=true) { - $this->setTemplateName($sTemplateName, $iSurveyId); // Check and set template name - $this->setIsStandard(); // Check if it is a CORE template - $this->setPath(); // Check and set path - $this->readManifest(); // Check and read the manifest to set local params + $this->setBasics($sTemplateName, $iSurveyId); $this->setMotherTemplates(); // Recursive mother templates configuration @$this->setThisTemplate(); // Set the main config values of this template $this->createTemplatePackage($this); // Create an asset package ready to be loaded return $this; } + + public function setBasics($sTemplateName='', $iSurveyId='') + { + $this->setTemplateName($sTemplateName, $iSurveyId); // Check and set template name + $this->setIsStandard(); // Check if it is a CORE template + $this->setPath(); // Check and set path + $this->readManifest(); // Check and read the manifest to set local params + } + /** * Add a file replacement entry * eg: css/template.css @@ -573,4 +666,5 @@ protected function getFrameworkAssetsReplacement( $sType ) } return $aAssetsToRemove; } + } diff --git a/application/views/admin/templateoptions/index.php b/application/views/admin/templateoptions/index.php index 549d569cc09..05053707313 100644 --- a/application/views/admin/templateoptions/index.php +++ b/application/views/admin/templateoptions/index.php @@ -16,9 +16,10 @@ ) )); ?> -

+

+ widget('bootstrap.widgets.TbGridView', array( 'dataProvider' => $model->search(), 'columns' => array( @@ -73,4 +74,36 @@
+ +

+
+
+ +
+ + + + + + + + + templatesWithNoDb as $oTemplate):?> + + + + + + + + + + + +
preview; ?>sTemplateName; ?>config->metadatas->description; ?>config->metadatas->extends; ?>buttons; ?>
+ +
+ +
+