Add php files
This commit is contained in:
301
modules/ModuleBuilder/parsers/views/AbstractMetaDataImplementation.php
Executable file
301
modules/ModuleBuilder/parsers/views/AbstractMetaDataImplementation.php
Executable file
@@ -0,0 +1,301 @@
|
||||
<?php
|
||||
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
|
||||
/*********************************************************************************
|
||||
* SugarCRM is a customer relationship management program developed by
|
||||
* SugarCRM, Inc. Copyright (C) 2004-2010 SugarCRM Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License version 3 as published by the
|
||||
* Free Software Foundation with the addition of the following permission added
|
||||
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
|
||||
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
|
||||
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License along with
|
||||
* this program; if not, see http://www.gnu.org/licenses or write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA.
|
||||
*
|
||||
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
|
||||
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "Powered by
|
||||
* SugarCRM" logo. If the display of the logo is not reasonably feasible for
|
||||
* technical reasons, the Appropriate Legal Notices must display the words
|
||||
* "Powered by SugarCRM".
|
||||
********************************************************************************/
|
||||
|
||||
require_once 'modules/ModuleBuilder/parsers/constants.php' ;
|
||||
|
||||
/*
|
||||
* Abstract base clase for Parser Implementations (using a Bridge Pattern)
|
||||
* The Implementations hide the differences between :
|
||||
* - Deployed modules (such as OOB modules and deployed ModuleBuilder modules) that are located in the /modules directory and have metadata in modules/<name>/metadata and in the custom directory
|
||||
* - WIP modules which are being worked on in ModuleBuilder and that are located in custom
|
||||
*/
|
||||
|
||||
|
||||
require_once 'modules/ModuleBuilder/parsers/views/History.php' ;
|
||||
|
||||
abstract class AbstractMetaDataImplementation
|
||||
{
|
||||
protected $_view ;
|
||||
protected $_moduleName ;
|
||||
protected $_viewdefs ;
|
||||
protected $_originalViewdefs = array();
|
||||
protected $_fielddefs ;
|
||||
protected $_sourceFilename = '' ; // the name of the file from which we loaded the definition we're working on - needed when we come to write out the historical record
|
||||
// would like this to be a constant, but alas, constants cannot contain arrays...
|
||||
protected $_fileVariables = array (
|
||||
MB_DASHLETSEARCH => 'dashletData',
|
||||
MB_DASHLET => 'dashletData',
|
||||
MB_POPUPSEARCH => 'popupMeta',
|
||||
MB_POPUPLIST => 'popupMeta',
|
||||
MB_LISTVIEW => 'listViewDefs',
|
||||
MB_BASICSEARCH => 'searchdefs',
|
||||
MB_ADVANCEDSEARCH => 'searchdefs',
|
||||
MB_EDITVIEW => 'viewdefs',
|
||||
MB_DETAILVIEW => 'viewdefs',
|
||||
MB_QUICKCREATE => 'viewdefs',
|
||||
) ;
|
||||
|
||||
/*
|
||||
* Getters for the definitions loaded by the Constructor
|
||||
*/
|
||||
function getViewdefs ()
|
||||
{
|
||||
$GLOBALS['log']->debug( get_class ( $this ) . '->getViewdefs:'.print_r($this->_viewdefs,true) ) ;
|
||||
return $this->_viewdefs ;
|
||||
}
|
||||
|
||||
function getOriginalViewdefs() {
|
||||
return $this->_originalViewdefs;
|
||||
}
|
||||
|
||||
function getFielddefs ()
|
||||
{
|
||||
return $this->_fielddefs ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Obtain a new accessor for the history of this layout
|
||||
* Ideally the History object would be a singleton; however given the use case (modulebuilder/studio) it's unlikely to be an issue
|
||||
*/
|
||||
function getHistory ()
|
||||
{
|
||||
return $this->_history ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Load a layout from a file, given a filename
|
||||
* Doesn't do any preprocessing on the viewdefs - just returns them as found for other classes to make sense of
|
||||
* @param string filename The full path to the file containing the layout
|
||||
* @return array The layout, null if the file does not exist
|
||||
*/
|
||||
protected function _loadFromFile ($filename)
|
||||
{
|
||||
// BEGIN ASSERTIONS
|
||||
if (! file_exists ( $filename ))
|
||||
{
|
||||
return null ;
|
||||
}
|
||||
// END ASSERTIONS
|
||||
$GLOBALS['log']->debug(get_class($this)."->_loadFromFile(): reading from ".$filename );
|
||||
require $filename ; // loads the viewdef - must be a require not require_once to ensure can reload if called twice in succession
|
||||
|
||||
// Check to see if we have the module name set as a variable rather than embedded in the $viewdef array
|
||||
// If we do, then we have to preserve the module variable when we write the file back out
|
||||
// This is a format used by ModuleBuilder templated modules to speed the renaming of modules
|
||||
// OOB Sugar modules don't use this format
|
||||
|
||||
$moduleVariables = array ( 'module_name' , '_module_name' , 'OBJECT_NAME' , '_object_name' ) ;
|
||||
|
||||
$variables = array ( ) ;
|
||||
foreach ( $moduleVariables as $name )
|
||||
{
|
||||
if (isset ( $$name ))
|
||||
{
|
||||
$variables [ $name ] = $$name ;
|
||||
}
|
||||
}
|
||||
|
||||
// Extract the layout definition from the loaded file - the layout definition is held under a variable name that varies between the various layout types (e.g., listviews hold it in listViewDefs, editviews in viewdefs)
|
||||
$viewVariable = $this->_fileVariables [ $this->_view ] ;
|
||||
$defs = $$viewVariable ;
|
||||
|
||||
// Now tidy up the module name in the viewdef array
|
||||
// MB created definitions store the defs under packagename_modulename and later methods that expect to find them under modulename will fail
|
||||
|
||||
if (isset ( $variables [ 'module_name' ] ))
|
||||
{
|
||||
$mbName = $variables [ 'module_name' ] ;
|
||||
if ($mbName != $this->_moduleName)
|
||||
{
|
||||
$defs [ $this->_moduleName ] = $defs [ $mbName ] ;
|
||||
unset ( $defs [ $mbName ] ) ;
|
||||
}
|
||||
}
|
||||
$this->_variables = $variables ;
|
||||
// now remove the modulename preamble from the loaded defs
|
||||
reset($defs);
|
||||
$temp = each($defs);
|
||||
|
||||
$GLOBALS['log']->debug( get_class ( $this ) . "->_loadFromFile: returning ".print_r($temp['value'],true)) ;
|
||||
return $temp['value']; // 'value' contains the value part of 'key'=>'value' part
|
||||
}
|
||||
|
||||
|
||||
protected function _loadFromPopupFile ($filename, $mod, $view, $forSave = false)
|
||||
{
|
||||
// BEGIN ASSERTIONS
|
||||
if (!file_exists ( $filename ))
|
||||
{
|
||||
return null ;
|
||||
}
|
||||
// END ASSERTIONS
|
||||
$GLOBALS['log']->debug(get_class($this)."->_loadFromFile(): reading from ".$filename );
|
||||
|
||||
if(!empty($mod)){
|
||||
$oldModStrings = $GLOBALS['mod_strings'];
|
||||
$GLOBALS['mod_strings'] = $mod;
|
||||
}
|
||||
|
||||
require $filename ; // loads the viewdef - must be a require not require_once to ensure can reload if called twice in succession
|
||||
$viewVariable = $this->_fileVariables [ $this->_view ] ;
|
||||
$defs = $$viewVariable ;
|
||||
if(!$forSave){
|
||||
//Now we will unset the reserve field in pop definition file.
|
||||
$limitFields = PopupMetaDataParser::$reserveProperties;
|
||||
foreach($limitFields as $v){
|
||||
if(isset($defs[$v])){
|
||||
unset($defs[$v]);
|
||||
}
|
||||
}
|
||||
if(isset($defs[PopupMetaDataParser::$defsMap[$view]])){
|
||||
$defs = $defs[PopupMetaDataParser::$defsMap[$view]];
|
||||
}else{
|
||||
//If there are no defs for this view, grab them from the non-popup view
|
||||
if ($view == MB_POPUPLIST)
|
||||
{
|
||||
$this->_view = MB_LISTVIEW;
|
||||
$defs = $this->_loadFromFile ( $this->getFileName ( MB_LISTVIEW, $this->_moduleName, MB_CUSTOMMETADATALOCATION ) ) ;
|
||||
if ($defs == null)
|
||||
$defs = $this->_loadFromFile ( $this->getFileName ( MB_LISTVIEW, $this->_moduleName, MB_BASEMETADATALOCATION ) ) ;
|
||||
$this->_view = $view;
|
||||
}
|
||||
else if ($view == MB_POPUPSEARCH)
|
||||
{
|
||||
$this->_view = MB_ADVANCEDSEARCH;
|
||||
$defs = $this->_loadFromFile ( $this->getFileName ( MB_ADVANCEDSEARCH, $this->_moduleName, MB_CUSTOMMETADATALOCATION ) ) ;
|
||||
if ($defs == null)
|
||||
$defs = $this->_loadFromFile ( $this->getFileName ( MB_ADVANCEDSEARCH, $this->_moduleName, MB_BASEMETADATALOCATION ) ) ;
|
||||
|
||||
if (isset($defs['layout']) && isset($defs['layout']['advanced_search']))
|
||||
$defs = $defs['layout']['advanced_search'];
|
||||
$this->_view = $view;
|
||||
}
|
||||
if ($defs == null)
|
||||
$defs = array();
|
||||
}
|
||||
}
|
||||
|
||||
$this->_variables = array();
|
||||
if(!empty($oldModStrings)){
|
||||
$GLOBALS['mod_strings'] = $oldModStrings;
|
||||
}
|
||||
return $defs;
|
||||
}
|
||||
|
||||
/*
|
||||
* Save a layout to a file
|
||||
* Must be the exact inverse of _loadFromFile
|
||||
* Obtains the additional variables, such as module_name, to include in beginning of the file (as required by ModuleBuilder) from the internal variable _variables, set in the Constructor
|
||||
* @param string filename The full path to the file to contain the layout
|
||||
* @param array defs Array containing the layout definition; the top level should be the definition itself; not the modulename or viewdef= preambles found in the file definitions
|
||||
* @param boolean useVariables Write out with placeholder entries for module name and object name - used by ModuleBuilder modules
|
||||
*/
|
||||
protected function _saveToFile ($filename , $defs , $useVariables = true, $forPopup = false )
|
||||
{
|
||||
|
||||
mkdir_recursive ( dirname ( $filename ) ) ;
|
||||
|
||||
$useVariables = (count ( $this->_variables ) > 0) && $useVariables ; // only makes sense to do the variable replace if we have variables to replace...
|
||||
|
||||
// create the new metadata file contents, and write it out
|
||||
$out = "<?php\n" ;
|
||||
if ($useVariables)
|
||||
{
|
||||
// write out the $<variable>=<modulename> lines
|
||||
foreach ( $this->_variables as $key => $value )
|
||||
{
|
||||
$out .= "\$$key = '" . $value . "';\n" ;
|
||||
}
|
||||
}
|
||||
|
||||
$viewVariable = $this->_fileVariables [ $this->_view ] ;
|
||||
if($forPopup){
|
||||
$out .= "\$$viewVariable = \n" . var_export_helper ( $defs ) ;
|
||||
}else{
|
||||
$out .= "\$$viewVariable [".(($useVariables) ? '$module_name' : "'$this->_moduleName'")."] = \n" . var_export_helper ( $defs ) ;
|
||||
}
|
||||
|
||||
$out .= ";\n?>\n" ;
|
||||
|
||||
if ( file_put_contents ( $filename, $out ) === false)
|
||||
$GLOBALS [ 'log' ]->fatal ( get_class($this).": could not write new viewdef file " . $filename ) ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fielddefs are obtained from two locations:
|
||||
*
|
||||
* 1. The starting point is the module's fielddefs, sourced from the Bean
|
||||
* 2. Second comes any overrides from the layouts themselves. Note though that only visible fields are included in a layoutdef, which
|
||||
* means fields that aren't present in the current layout may have a layout defined in a lower-priority layoutdef, for example, the base layoutdef
|
||||
*
|
||||
* Thus to determine the current fielddef for any given field, we take the fielddef defined in the module's Bean and then override with first the base layout,
|
||||
* then the customlayout, then finally the working layout...
|
||||
*
|
||||
* The complication is that although generating these merged fielddefs is naturally a method of the implementation, not the parser,
|
||||
* we therefore lack knowledge as to which type of layout we are merging - EditView or ListView. So we can't use internal knowledge of the
|
||||
* layout to locate the field definitions. Instead, we need to look for sections of the layout that match the template for a field definition...
|
||||
*/
|
||||
function _mergeFielddefs ( &$fielddefs , $layout )
|
||||
{
|
||||
foreach ( $layout as $key => $def )
|
||||
{
|
||||
|
||||
if ( (string) $key == 'templateMeta' )
|
||||
continue ;
|
||||
|
||||
if ( is_array ( $def ) )
|
||||
{
|
||||
if ( isset ( $def [ 'name' ] ) && ! is_array ( $def [ 'name' ] ) ) // found a 'name' definition, that is not the definition of a field called name :)
|
||||
{
|
||||
// if this is a module field, then merge in the definition, otherwise this is a new field defined in the layout, so just take the definition
|
||||
$fielddefs [ $def [ 'name'] ] = ( isset ($fielddefs [ $def [ 'name' ] ] ) ) ? array_merge ( $fielddefs [ $def [ 'name' ] ], $def ) : $def ;
|
||||
}
|
||||
else if ( isset ( $def [ 'label' ] ) || isset ( $def [ 'vname' ] ) || isset($def ['widget_class']) ) // dealing with a listlayout which lacks 'name' keys, but which does have 'label' keys
|
||||
{
|
||||
$key = strtolower ( $key ) ;
|
||||
$fielddefs [ $key ] = ( isset ($fielddefs [ $key ] ) ) ? array_merge ( $fielddefs [ $key ], $def ) : $def ;
|
||||
}
|
||||
else
|
||||
$this->_mergeFielddefs( $fielddefs , $def ) ;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
127
modules/ModuleBuilder/parsers/views/AbstractMetaDataParser.php
Executable file
127
modules/ModuleBuilder/parsers/views/AbstractMetaDataParser.php
Executable file
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
|
||||
/*********************************************************************************
|
||||
* SugarCRM is a customer relationship management program developed by
|
||||
* SugarCRM, Inc. Copyright (C) 2004-2010 SugarCRM Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License version 3 as published by the
|
||||
* Free Software Foundation with the addition of the following permission added
|
||||
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
|
||||
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
|
||||
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License along with
|
||||
* this program; if not, see http://www.gnu.org/licenses or write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA.
|
||||
*
|
||||
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
|
||||
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "Powered by
|
||||
* SugarCRM" logo. If the display of the logo is not reasonably feasible for
|
||||
* technical reasons, the Appropriate Legal Notices must display the words
|
||||
* "Powered by SugarCRM".
|
||||
********************************************************************************/
|
||||
|
||||
abstract class AbstractMetaDataParser
|
||||
{
|
||||
|
||||
//Make these properties public for now until we can create some usefull accessors
|
||||
public $_fielddefs ;
|
||||
public $_viewdefs ;
|
||||
protected $_moduleName ;
|
||||
protected $implementation ; // the DeployedMetaDataImplementation or UndeployedMetaDataImplementation object to handle the reading and writing of files and field data
|
||||
|
||||
function getLayoutAsArray ()
|
||||
{
|
||||
$viewdefs = $this->_panels ;
|
||||
}
|
||||
|
||||
function getLanguage ()
|
||||
{
|
||||
return $this->implementation->getLanguage () ;
|
||||
}
|
||||
|
||||
function getHistory ()
|
||||
{
|
||||
return $this->implementation->getHistory () ;
|
||||
}
|
||||
|
||||
function removeField ($fieldName)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Is this field something we wish to show in Studio/ModuleBuilder layout editors?
|
||||
* @param array $def Field definition in the standard SugarBean field definition format - name, vname, type and so on
|
||||
* @return boolean True if ok to show, false otherwise
|
||||
*/
|
||||
static function validField ( $def, $view = "")
|
||||
{
|
||||
//Studio invisible fields should always be hidden
|
||||
if (isset ($def[ 'studio' ] ) )
|
||||
{
|
||||
if (is_array($def [ 'studio' ]))
|
||||
{
|
||||
if (!empty($view) && isset($def [ 'studio' ][$view]))
|
||||
return $def [ 'studio' ][$view] !== false && $def [ 'studio' ][$view] != 'false' && $def [ 'studio' ][$view] != 'hidden';
|
||||
if (isset($def [ 'studio' ]['visible']))
|
||||
return $def [ 'studio' ]['visible'];
|
||||
} else {
|
||||
return ($def [ 'studio' ] != 'false' && $def [ 'studio' ] != 'hidden' && $def [ 'studio' ] !== false) ;
|
||||
}
|
||||
}
|
||||
|
||||
// bug 19656: this test changed after 5.0.0b - we now remove all ID type fields - whether set as type, or dbtype, from the fielddefs
|
||||
return
|
||||
(
|
||||
(
|
||||
(empty ( $def [ 'source' ] ) || $def [ 'source' ] == 'db' || $def [ 'source' ] == 'custom_fields')
|
||||
&& isset($def [ 'type' ]) && $def [ 'type' ] != 'id' && $def [ 'type' ] != 'parent_type'
|
||||
&& (empty ( $def [ 'dbType' ] ) || $def [ 'dbType' ] != 'id')
|
||||
&& ( isset ( $def [ 'name' ] ) && strcmp ( $def [ 'name' ] , 'deleted' ) != 0 )
|
||||
) // db and custom fields that aren't ID fields
|
||||
||
|
||||
// exclude fields named *_name regardless of their type...just convention
|
||||
(isset ( $def [ 'name' ] ) && substr ( $def [ 'name' ], -5 ) === '_name' ) ) ;
|
||||
}
|
||||
|
||||
protected function _standardizeFieldLabels ( &$fielddefs )
|
||||
{
|
||||
foreach ( $fielddefs as $key => $def )
|
||||
{
|
||||
if ( !isset ($def [ 'label' ] ) )
|
||||
{
|
||||
$fielddefs [ $key ] [ 'label'] = ( isset ( $def [ 'vname' ] ) ) ? $def [ 'vname' ] : $key ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract static function _trimFieldDefs ( $def ) ;
|
||||
|
||||
public function getRequiredFields(){
|
||||
$fieldDefs = $this->implementation->getFielddefs();
|
||||
$newAry = array();
|
||||
foreach($fieldDefs as $field){
|
||||
if(isset($field['required']) && $field['required'] && isset($field['name'])){
|
||||
array_push($newAry , '"'.$field['name'].'"');
|
||||
}
|
||||
}
|
||||
return $newAry;
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
||||
175
modules/ModuleBuilder/parsers/views/DashletMetaDataParser.php
Executable file
175
modules/ModuleBuilder/parsers/views/DashletMetaDataParser.php
Executable file
@@ -0,0 +1,175 @@
|
||||
<?php
|
||||
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
|
||||
/*********************************************************************************
|
||||
* SugarCRM is a customer relationship management program developed by
|
||||
* SugarCRM, Inc. Copyright (C) 2004-2010 SugarCRM Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License version 3 as published by the
|
||||
* Free Software Foundation with the addition of the following permission added
|
||||
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
|
||||
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
|
||||
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License along with
|
||||
* this program; if not, see http://www.gnu.org/licenses or write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA.
|
||||
*
|
||||
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
|
||||
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "Powered by
|
||||
* SugarCRM" logo. If the display of the logo is not reasonably feasible for
|
||||
* technical reasons, the Appropriate Legal Notices must display the words
|
||||
* "Powered by SugarCRM".
|
||||
********************************************************************************/
|
||||
|
||||
require_once ('modules/ModuleBuilder/parsers/views/ListLayoutMetaDataParser.php') ;
|
||||
require_once ('modules/ModuleBuilder/parsers/views/SearchViewMetaDataParser.php') ;
|
||||
require_once 'modules/ModuleBuilder/parsers/constants.php' ;
|
||||
|
||||
class DashletMetaDataParser extends ListLayoutMetaDataParser
|
||||
{
|
||||
|
||||
// Columns is used by the view to construct the listview - each column is built by calling the named function
|
||||
public $columns = array ( 'LBL_DEFAULT' => 'getDefaultFields' , 'LBL_AVAILABLE' => 'getAdditionalFields' , 'LBL_HIDDEN' => 'getAvailableFields' ) ;
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
* Must set:
|
||||
* $this->columns Array of 'Column LBL'=>function_to_retrieve_fields_for_this_column() - expected by the view
|
||||
*
|
||||
* @param string moduleName The name of the module to which this listview belongs
|
||||
* @param string packageName If not empty, the name of the package to which this listview belongs
|
||||
*/
|
||||
function __construct ($view, $moduleName , $packageName = '')
|
||||
{
|
||||
|
||||
$this->search = ($view == MB_DASHLETSEARCH) ? true : false;
|
||||
$this->_moduleName = $moduleName;
|
||||
$this->_packageName = $packageName;
|
||||
$this->_view = $view ;
|
||||
if ($this->search)
|
||||
{
|
||||
$this->columns = array ( 'LBL_DEFAULT' => 'getAdditionalFields' , 'LBL_HIDDEN' => 'getAvailableFields' ) ;
|
||||
parent::__construct ( MB_DASHLETSEARCH, $moduleName, $packageName ) ;
|
||||
} else
|
||||
{
|
||||
parent::__construct ( MB_DASHLET, $moduleName, $packageName ) ;
|
||||
}
|
||||
$this->_viewdefs = $this->mergeFieldDefinitions($this->_viewdefs, $this->_fielddefs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dashlets contain both a searchview and list view definition, therefore we need to merge only the relevant info
|
||||
*/
|
||||
function mergeFieldDefinitions ( $viewdefs, $fielddefs ) {
|
||||
if ($this->_view == MB_DASHLETSEARCH && isset($viewdefs['searchfields']))
|
||||
{
|
||||
//Remove any relate fields from the possible defs as they will break the homepage
|
||||
foreach($fielddefs as $id=>$def) {
|
||||
if (isset($def['type']) && $def['type'] == 'relate') {
|
||||
if( isset($fielddefs[$id]['id_name'])){
|
||||
$fielddefs[$fielddefs[$id]['id_name']] = $def;
|
||||
unset($fielddefs[$id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
$viewdefs = array_change_key_case($viewdefs['searchfields']);
|
||||
$viewdefs = $this->_viewdefs = $this->convertSearchToListDefs($viewdefs);
|
||||
}
|
||||
else if ($this->_view == MB_DASHLET && isset($viewdefs['columns']))
|
||||
{
|
||||
$viewdefs = $this->_viewdefs = array_change_key_case($viewdefs['columns']);
|
||||
$viewdefs = $this->_viewdefs = $this->convertSearchToListDefs($viewdefs);
|
||||
}
|
||||
|
||||
return $viewdefs;
|
||||
}
|
||||
|
||||
function convertSearchToListDefs($defs) {
|
||||
$temp = array();
|
||||
foreach($defs as $key=>$value) {
|
||||
$temp[$key] = $value;
|
||||
if (!isset ($temp[$key]['name'])) {
|
||||
$temp[$key]['name'] = $key;
|
||||
}
|
||||
}
|
||||
return $temp;
|
||||
}
|
||||
|
||||
private function ConvertSearchToDashletDefs($defs) {
|
||||
$temp = array();
|
||||
foreach($defs as $key=>$value) {
|
||||
if($value['default']) {
|
||||
//$temp[$key] = $value;
|
||||
$temp[$key] = array('default' => '');
|
||||
}else{
|
||||
$temp[$key] = $value;
|
||||
}
|
||||
}
|
||||
return $temp;
|
||||
}
|
||||
|
||||
function handleSave ($populate = true)
|
||||
{
|
||||
if (empty ( $this->_packageName ))
|
||||
{
|
||||
foreach(array(MB_CUSTOMMETADATALOCATION , MB_BASEMETADATALOCATION) as $value){
|
||||
$file = $this->implementation->getFileName(MB_DASHLET, $this->_moduleName, $value);
|
||||
if(file_exists($file)){
|
||||
break;
|
||||
}
|
||||
}
|
||||
$writeTodashletName = $dashletName = $this->implementation->getLanguage().'Dashlet';
|
||||
if(!file_exists($file)){
|
||||
$file = "modules/{$this->_moduleName}/Dashlets/My{$this->_moduleName}Dashlet/My{$this->_moduleName}Dashlet.data.php";
|
||||
$dashletName = 'My'.$this->implementation->getLanguage().'Dashlet';
|
||||
}
|
||||
$writeFile = $this->implementation->getFileName(MB_DASHLET, $this->_moduleName);
|
||||
if(!file_exists($writeFile)){
|
||||
mkdir_recursive ( dirname ( $writeFile ) ) ;
|
||||
}
|
||||
}
|
||||
else{
|
||||
$writeFile = $file = $this->implementation->getFileName(MB_DASHLET, $this->_moduleName, $this->_packageName);
|
||||
$writeTodashletName = $dashletName =$this->implementation->module->key_name . 'Dashlet';
|
||||
}
|
||||
|
||||
$this->implementation->_history->append ( $file ) ;
|
||||
if ($populate)
|
||||
$this->_populateFromRequest() ;
|
||||
$out = "<?php\n" ;
|
||||
|
||||
require($file);
|
||||
if (!isset($dashletData[$dashletName])) {
|
||||
sugar_die ("unable to load Module Dashlet Definition");
|
||||
}
|
||||
if ($fh = sugar_fopen ( $writeFile, 'w' ))
|
||||
{
|
||||
if ($this->_view == MB_DASHLETSEARCH)
|
||||
{
|
||||
$dashletData[$dashletName]['searchFields'] = $this->ConvertSearchToDashletDefs($this->_viewdefs);
|
||||
} else
|
||||
{
|
||||
$dashletData[$dashletName]['columns'] = $this->_viewdefs;
|
||||
}
|
||||
$out .= "\$dashletData['$writeTodashletName']['searchFields'] = " . var_export_helper ($dashletData[$dashletName]['searchFields']) . ";\n";
|
||||
$out .= "\$dashletData['$writeTodashletName']['columns'] = " . var_export_helper ($dashletData[$dashletName]['columns']) . ";\n";
|
||||
fputs ( $fh, $out) ;
|
||||
fclose ( $fh ) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
364
modules/ModuleBuilder/parsers/views/DeployedMetaDataImplementation.php
Executable file
364
modules/ModuleBuilder/parsers/views/DeployedMetaDataImplementation.php
Executable file
@@ -0,0 +1,364 @@
|
||||
<?php
|
||||
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
|
||||
/*********************************************************************************
|
||||
* SugarCRM is a customer relationship management program developed by
|
||||
* SugarCRM, Inc. Copyright (C) 2004-2010 SugarCRM Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License version 3 as published by the
|
||||
* Free Software Foundation with the addition of the following permission added
|
||||
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
|
||||
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
|
||||
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License along with
|
||||
* this program; if not, see http://www.gnu.org/licenses or write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA.
|
||||
*
|
||||
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
|
||||
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "Powered by
|
||||
* SugarCRM" logo. If the display of the logo is not reasonably feasible for
|
||||
* technical reasons, the Appropriate Legal Notices must display the words
|
||||
* "Powered by SugarCRM".
|
||||
********************************************************************************/
|
||||
/*
|
||||
* Implementation class (following a Bridge Pattern) for handling loading and saving deployed module metadata
|
||||
* For example, listview or editview viewdefs
|
||||
*/
|
||||
|
||||
require_once 'modules/ModuleBuilder/parsers/views/AbstractMetaDataImplementation.php' ;
|
||||
require_once 'modules/ModuleBuilder/parsers/views/MetaDataImplementationInterface.php' ;
|
||||
require_once 'modules/ModuleBuilder/parsers/views/ListLayoutMetaDataParser.php' ;
|
||||
require_once 'modules/ModuleBuilder/parsers/views/GridLayoutMetaDataParser.php' ;
|
||||
require_once 'modules/ModuleBuilder/parsers/views/PopupMetaDataParser.php' ;
|
||||
require_once 'modules/ModuleBuilder/Module/StudioModuleFactory.php' ;
|
||||
require_once 'modules/ModuleBuilder/parsers/constants.php' ;
|
||||
|
||||
class DeployedMetaDataImplementation extends AbstractMetaDataImplementation implements MetaDataImplementationInterface
|
||||
{
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
* @param string $view
|
||||
* @param string $moduleName
|
||||
* @throws Exception Thrown if the provided view doesn't exist for this module
|
||||
*/
|
||||
function __construct ($view , $moduleName)
|
||||
{
|
||||
|
||||
// BEGIN ASSERTIONS
|
||||
if (! isset ( $this->_fileVariables [ $view ] ))
|
||||
{
|
||||
sugar_die ( get_class ( $this ) . ": View $view is not supported" ) ;
|
||||
}
|
||||
if (! isset ( $GLOBALS [ 'beanList' ] [ $moduleName ] ))
|
||||
{
|
||||
sugar_die ( get_class ( $this ) . ": Modulename $moduleName is not a Deployed Module" ) ;
|
||||
}
|
||||
// END ASSERTIONS
|
||||
|
||||
$this->_view = strtolower ( $view ) ;
|
||||
$this->_moduleName = $moduleName ;
|
||||
|
||||
$module = StudioModuleFactory::getStudioModule( $moduleName ) ;
|
||||
$this->module_dir = $module->seed->module_dir;
|
||||
$fielddefs = $module->getFields();
|
||||
|
||||
$loaded = null ;
|
||||
foreach ( array ( MB_BASEMETADATALOCATION , MB_CUSTOMMETADATALOCATION , MB_WORKINGMETADATALOCATION , MB_HISTORYMETADATALOCATION ) as $type )
|
||||
{
|
||||
$this->_sourceFilename = $this->getFileName ( $view, $moduleName, $type ) ;
|
||||
if($view == MB_POPUPSEARCH || $view == MB_POPUPLIST){
|
||||
global $current_language;
|
||||
$mod = return_module_language($current_language , $moduleName);
|
||||
$layout = $this->_loadFromPopupFile ( $this->_sourceFilename , $mod, $view);
|
||||
}else{
|
||||
$layout = $this->_loadFromFile ( $this->_sourceFilename );
|
||||
}
|
||||
if ( null !== $layout )
|
||||
{
|
||||
// merge in the fielddefs from this layout
|
||||
$this->_mergeFielddefs ( $fielddefs , $layout ) ;
|
||||
$loaded = $layout ;
|
||||
}
|
||||
}
|
||||
|
||||
if ($loaded === null)
|
||||
{
|
||||
switch ( $view )
|
||||
{
|
||||
case MB_QUICKCREATE:
|
||||
// Special handling for QuickCreates - if we don't have a QuickCreate definition in the usual places, then use an EditView
|
||||
|
||||
$loaded = $this->_loadFromFile ( $this->getFileName ( MB_EDITVIEW, $this->_moduleName, MB_BASEMETADATALOCATION ) ) ;
|
||||
|
||||
if ($loaded === null)
|
||||
throw new Exception( get_class ( $this ) . ": cannot convert from EditView to QuickCreate for Module $this->_moduleName - definitions for EditView are missing" ) ;
|
||||
|
||||
// Now change the array index
|
||||
$temp = $loaded [ GridLayoutMetaDataParser::$variableMap [ MB_EDITVIEW ] ] ;
|
||||
unset ( $loaded [ GridLayoutMetaDataParser::$variableMap [ MB_EDITVIEW ] ] ) ;
|
||||
$loaded [ GridLayoutMetaDataParser::$variableMap [ MB_QUICKCREATE ] ] = $temp ;
|
||||
// finally, save out our new definition so that we have a base record for the history to work from
|
||||
$this->_sourceFilename = self::getFileName ( MB_QUICKCREATE, $this->_moduleName, MB_CUSTOMMETADATALOCATION ) ;
|
||||
$this->_saveToFile ( $this->_sourceFilename, $loaded ) ;
|
||||
$this->_mergeFielddefs ( $fielddefs , $loaded ) ;
|
||||
break;
|
||||
|
||||
case MB_DASHLETSEARCH:
|
||||
case MB_DASHLET:
|
||||
$type = $module->getType () ;
|
||||
$this->_sourceFilename = self::getFileName ( $view, $moduleName, MB_CUSTOMMETADATALOCATION ) ;
|
||||
$needSave = false;
|
||||
if(file_exists( "custom/modules/{$moduleName}/metadata/".basename ( $this->_sourceFilename))){
|
||||
$loaded = $this->_loadFromFile ( "custom/modules/{$moduleName}/metadata/".basename ( $this->_sourceFilename) ) ;
|
||||
}
|
||||
elseif(file_exists(
|
||||
"modules/{$moduleName}/Dashlets/My{$moduleName}Dashlet/My{$moduleName}Dashlet.data.php")){
|
||||
$loaded = $this->_loadFromFile ( "modules/{$moduleName}/Dashlets/My{$moduleName}Dashlet/My{$moduleName}Dashlet.data.php");
|
||||
}
|
||||
else{
|
||||
$loaded = $this->_loadFromFile ( "include/SugarObjects/templates/$type/metadata/".basename ( $this->_sourceFilename ) ) ;
|
||||
$needSave = true;
|
||||
}
|
||||
if ($loaded === null)
|
||||
throw new Exception( get_class ( $this ) . ": cannot create dashlet view for module $moduleName - definitions for $view are missing in the SugarObject template for type $type" ) ;
|
||||
$loaded = $this->replaceVariables($loaded, $module);
|
||||
$temp = $this->_moduleName;
|
||||
if($needSave){
|
||||
$this->_moduleName = $this->_moduleName.'Dashlet';
|
||||
$this->_saveToFile ( $this->_sourceFilename, $loaded,false) ; // write out without the placeholder module_name and object
|
||||
$this->_moduleName = $temp;
|
||||
unset($temp);
|
||||
}
|
||||
$this->_mergeFielddefs ( $fielddefs , $loaded ) ;
|
||||
break;
|
||||
case MB_POPUPLIST:
|
||||
case MB_POPUPSEARCH:
|
||||
$type = $module->getType () ;
|
||||
$this->_sourceFilename = self::getFileName ( $view, $moduleName, MB_CUSTOMMETADATALOCATION ) ;
|
||||
|
||||
// Now we can copy the wireless view from the template
|
||||
global $current_language;
|
||||
$mod = return_module_language($current_language , $moduleName);
|
||||
$loadedForWrite = $this->_loadFromPopupFile ( "include/SugarObjects/templates/$type/metadata/".basename ( $this->_sourceFilename ) , $mod, $view, true);
|
||||
if ($loadedForWrite === null)
|
||||
throw new Exception( get_class ( $this ) . ": cannot create popup view for module $moduleName - definitions for $view are missing in the SugarObject template for type $type" ) ;
|
||||
$loadedForWrite = $this->replaceVariables($loadedForWrite, $module);
|
||||
$this->_saveToFile ( $this->_sourceFilename, $loadedForWrite , false , true) ; // write out without the placeholder module_name and object
|
||||
$loaded = $this->_loadFromPopupFile ( "include/SugarObjects/templates/$type/metadata/".basename ( $this->_sourceFilename ) , $mod, $view);
|
||||
$this->_mergeFielddefs ( $fielddefs , $loaded ) ;
|
||||
break;
|
||||
default:
|
||||
|
||||
}
|
||||
if ( $loaded === null )
|
||||
throw new Exception( get_class ( $this ) . ": view definitions for View $this->_view and Module $this->_moduleName are missing" ) ;
|
||||
}
|
||||
|
||||
$this->_viewdefs = $loaded ;
|
||||
// Set the original Viewdefs - required to ensure we don't lose fields from the base layout
|
||||
// Check the base location first, then if nothing is there (which for example, will be the case for some QuickCreates, and some mobile layouts - see above)
|
||||
// we need to check the custom location where the derived layouts will be
|
||||
foreach ( array ( MB_BASEMETADATALOCATION , MB_CUSTOMMETADATALOCATION ) as $type )
|
||||
{
|
||||
$sourceFilename = $this->getFileName ( $view, $moduleName, $type ) ;
|
||||
if($view == MB_POPUPSEARCH || $view == MB_POPUPLIST){
|
||||
global $current_language;
|
||||
$mod = return_module_language($current_language , $moduleName);
|
||||
$layout = $this->_loadFromPopupFile ( $sourceFilename , $mod, $view);
|
||||
}else{
|
||||
$layout = $this->_loadFromFile ( $sourceFilename );
|
||||
}
|
||||
if ( null !== ($layout ) )
|
||||
{
|
||||
$this->_originalViewdefs = $layout ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
//For quick create viewdefs, if there is no quickcreatedefs.php under MB_BASEMETADATALOCATION, the original defs is editview defs.
|
||||
if ($view == MB_QUICKCREATE) {
|
||||
foreach(array(MB_QUICKCREATE, MB_EDITVIEW) as $v){
|
||||
$sourceFilename = $this->getFileName($v, $moduleName, MB_BASEMETADATALOCATION ) ;
|
||||
if (file_exists($sourceFilename )) {
|
||||
$layout = $this->_loadFromFile($sourceFilename );
|
||||
if (null !== $layout && isset($layout[GridLayoutMetaDataParser::$variableMap[$v]])) {
|
||||
$layout = array(GridLayoutMetaDataParser::$variableMap[MB_QUICKCREATE] => $layout[GridLayoutMetaDataParser::$variableMap[$v]]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (null === $layout) {
|
||||
$sourceFilename = $this->getFileName($view, $moduleName, MB_CUSTOMMETADATALOCATION );
|
||||
$layout = $this->_loadFromFile($sourceFilename );
|
||||
}
|
||||
|
||||
if (null !== $layout ) {
|
||||
$this->_originalViewdefs = $layout ;
|
||||
}
|
||||
}
|
||||
|
||||
$this->_fielddefs = $fielddefs ;
|
||||
$this->_history = new History ( $this->getFileName ( $view, $moduleName, MB_HISTORYMETADATALOCATION ) ) ;
|
||||
|
||||
}
|
||||
|
||||
function getLanguage ()
|
||||
{
|
||||
return $this->_moduleName ;
|
||||
}
|
||||
|
||||
function getOriginalViewdefs()
|
||||
{
|
||||
return $this->_originalViewdefs;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Save a draft layout
|
||||
* @param array defs Layout definition in the same format as received by the constructor
|
||||
*/
|
||||
function save ($defs)
|
||||
{
|
||||
//If we are pulling from the History Location, that means we did a restore, and we need to save the history for the previous file.
|
||||
if ($this->_sourceFilename == $this->getFileName ( $this->_view, $this->_moduleName, MB_HISTORYMETADATALOCATION )) {
|
||||
foreach ( array ( MB_WORKINGMETADATALOCATION , MB_CUSTOMMETADATALOCATION , MB_BASEMETADATALOCATION ) as $type ) {
|
||||
if (file_exists($this->getFileName ( $this->_view, $this->_moduleName, $type ))) {
|
||||
$this->_history->append ( $this->getFileName ( $this->_view, $this->_moduleName, $type )) ;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->_history->append ( $this->_sourceFilename ) ;
|
||||
}
|
||||
|
||||
$GLOBALS [ 'log' ]->debug ( get_class ( $this ) . "->save(): writing to " . $this->getFileName ( $this->_view, $this->_moduleName, MB_WORKINGMETADATALOCATION ) ) ;
|
||||
$this->_saveToFile ( $this->getFileName ( $this->_view, $this->_moduleName, MB_WORKINGMETADATALOCATION ), $defs ) ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Deploy a layout
|
||||
* @param array defs Layout definition in the same format as received by the constructor
|
||||
*/
|
||||
function deploy ($defs)
|
||||
{
|
||||
if ($this->_sourceFilename == $this->getFileName ( $this->_view, $this->_moduleName, MB_HISTORYMETADATALOCATION )) {
|
||||
foreach ( array ( MB_WORKINGMETADATALOCATION , MB_CUSTOMMETADATALOCATION , MB_BASEMETADATALOCATION ) as $type ) {
|
||||
if (file_exists($this->getFileName ( $this->_view, $this->_moduleName, $type ))) {
|
||||
$this->_history->append ( $this->getFileName ( $this->_view, $this->_moduleName, $type )) ;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->_history->append ( $this->_sourceFilename ) ;
|
||||
}
|
||||
// when we deploy get rid of the working file; we have the changes in the MB_CUSTOMMETADATALOCATION so no need for a redundant copy in MB_WORKINGMETADATALOCATION
|
||||
// this also simplifies manual editing of layouts. You can now switch back and forth between Studio and manual changes without having to keep these two locations in sync
|
||||
$workingFilename = $this->getFileName ( $this->_view, $this->_moduleName, MB_WORKINGMETADATALOCATION ) ;
|
||||
|
||||
if (file_exists ( $workingFilename ))
|
||||
unlink ( $this->getFileName ( $this->_view, $this->_moduleName, MB_WORKINGMETADATALOCATION ) ) ;
|
||||
$filename = $this->getFileName ( $this->_view, $this->_moduleName, MB_CUSTOMMETADATALOCATION ) ;
|
||||
$GLOBALS [ 'log' ]->debug ( get_class ( $this ) . "->deploy(): writing to " . $filename ) ;
|
||||
$this->_saveToFile ( $filename, $defs ) ;
|
||||
|
||||
// now clear the cache so that the results are immediately visible
|
||||
include_once ('include/TemplateHandler/TemplateHandler.php') ;
|
||||
TemplateHandler::clearCache ( $this->_moduleName ) ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct a full pathname for the requested metadata
|
||||
* Can be called statically
|
||||
* @param string view The view type, that is, EditView, DetailView etc
|
||||
* @param string modulename The name of the module that will use this layout
|
||||
* @param string type
|
||||
*/
|
||||
public static function getFileName ($view , $moduleName , $type = MB_CUSTOMMETADATALOCATION)
|
||||
{
|
||||
|
||||
$pathMap = array ( MB_BASEMETADATALOCATION => '' , MB_CUSTOMMETADATALOCATION => 'custom/' , MB_WORKINGMETADATALOCATION => 'custom/working/' , MB_HISTORYMETADATALOCATION => 'custom/history/' ) ;
|
||||
$type = strtolower ( $type ) ;
|
||||
|
||||
$filenames = array (
|
||||
MB_DASHLETSEARCH => 'dashletviewdefs',
|
||||
MB_DASHLET => 'dashletviewdefs',
|
||||
MB_POPUPSEARCH => 'popupdefs',
|
||||
MB_POPUPLIST => 'popupdefs',
|
||||
MB_LISTVIEW => 'listviewdefs' ,
|
||||
MB_BASICSEARCH => 'searchdefs' ,
|
||||
MB_ADVANCEDSEARCH => 'searchdefs' ,
|
||||
MB_EDITVIEW => 'editviewdefs' ,
|
||||
MB_DETAILVIEW => 'detailviewdefs' ,
|
||||
MB_QUICKCREATE => 'quickcreatedefs',
|
||||
) ;
|
||||
|
||||
// BEGIN ASSERTIONS
|
||||
if (! isset ( $pathMap [ $type ] ))
|
||||
{
|
||||
sugar_die ( "DeployedMetaDataImplementation->getFileName(): Type $type is not recognized" ) ;
|
||||
}
|
||||
if (! isset ( $filenames [ $view ] ))
|
||||
{
|
||||
sugar_die ( "DeployedMetaDataImplementation->getFileName(): View $view is not recognized" ) ;
|
||||
}
|
||||
// END ASSERTIONS
|
||||
|
||||
|
||||
|
||||
// Construct filename
|
||||
return $pathMap [ $type ] . 'modules/' . $moduleName . '/metadata/' . $filenames [ $view ] . '.php' ;
|
||||
}
|
||||
|
||||
private function replaceVariables($defs, $module) {
|
||||
$var_values = array(
|
||||
"<object_name>" => $module->seed->object_name,
|
||||
"<_object_name>" => strtolower($module->seed->object_name),
|
||||
"<OBJECT_NAME>" => strtoupper($module->seed->object_name),
|
||||
"<module_name>" => $module->seed->module_dir,
|
||||
'<_module_name>'=> strtolower ( $module->seed->module_dir )
|
||||
);
|
||||
return $this->recursiveVariableReplace($defs, $module, $var_values);
|
||||
}
|
||||
|
||||
public function getModuleDir(){
|
||||
return $this->module_dir;
|
||||
}
|
||||
|
||||
private function recursiveVariableReplace($arr, $module, $replacements) {
|
||||
$ret = array();
|
||||
foreach ($arr as $key => $val) {
|
||||
if (is_array($val)) {
|
||||
$newkey = $key;
|
||||
$val = $this->recursiveVariableReplace($val, $module, $replacements);
|
||||
foreach ($replacements as $var => $rep) {
|
||||
$newkey = str_replace($var, $rep, $newkey);
|
||||
}
|
||||
$ret[$newkey] = $val;
|
||||
} else {
|
||||
$newkey = $key;
|
||||
$newval = $val;
|
||||
foreach ($replacements as $var => $rep) {
|
||||
$newkey = str_replace($var, $rep, $newkey);
|
||||
$newval = str_replace($var, $rep, $newval);
|
||||
}
|
||||
$ret[$newkey] = $newval;
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
168
modules/ModuleBuilder/parsers/views/DeployedSubpanelImplementation.php
Executable file
168
modules/ModuleBuilder/parsers/views/DeployedSubpanelImplementation.php
Executable file
@@ -0,0 +1,168 @@
|
||||
<?php
|
||||
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
|
||||
/*********************************************************************************
|
||||
* SugarCRM is a customer relationship management program developed by
|
||||
* SugarCRM, Inc. Copyright (C) 2004-2010 SugarCRM Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License version 3 as published by the
|
||||
* Free Software Foundation with the addition of the following permission added
|
||||
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
|
||||
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
|
||||
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License along with
|
||||
* this program; if not, see http://www.gnu.org/licenses or write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA.
|
||||
*
|
||||
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
|
||||
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "Powered by
|
||||
* SugarCRM" logo. If the display of the logo is not reasonably feasible for
|
||||
* technical reasons, the Appropriate Legal Notices must display the words
|
||||
* "Powered by SugarCRM".
|
||||
********************************************************************************/
|
||||
/*
|
||||
* Changes to AbstractSubpanelImplementation for DeployedSubpanels
|
||||
* The main differences are in the load and save of the definitions
|
||||
* For subpanels we must make use of the SubPanelDefinitions class to do this; this also means that the history mechanism,
|
||||
* which tracks files, not objects, needs us to create an intermediate file representation of the definition that it can manage and restore
|
||||
*/
|
||||
|
||||
require_once 'modules/ModuleBuilder/parsers/views/MetaDataImplementationInterface.php' ;
|
||||
require_once 'modules/ModuleBuilder/parsers/views/AbstractMetaDataImplementation.php' ;
|
||||
require_once 'modules/ModuleBuilder/parsers/constants.php' ;
|
||||
|
||||
class DeployedSubpanelImplementation extends AbstractMetaDataImplementation implements MetaDataImplementationInterface
|
||||
{
|
||||
|
||||
const HISTORYFILENAME = 'restored.php' ;
|
||||
const HISTORYVARIABLENAME = 'layout_defs' ;
|
||||
|
||||
private $_subpanelName ;
|
||||
private $_aSubPanelObject ; // an aSubPanel Object representing the current subpanel
|
||||
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
* @param string subpanelName The name of this subpanel
|
||||
* @param string moduleName The name of the module to which this subpanel belongs
|
||||
*/
|
||||
function __construct ($subpanelName , $moduleName)
|
||||
{
|
||||
$GLOBALS [ 'log' ]->debug ( get_class ( $this ) . "->__construct($subpanelName , $moduleName)" ) ;
|
||||
$this->_subpanelName = $subpanelName ;
|
||||
$this->_moduleName = $moduleName ;
|
||||
|
||||
// BEGIN ASSERTIONS
|
||||
if (! isset ( $GLOBALS [ 'beanList' ] [ $moduleName ] ))
|
||||
{
|
||||
sugar_die ( get_class ( $this ) . ": Modulename $moduleName is not a Deployed Module" ) ;
|
||||
}
|
||||
// END ASSERTIONS
|
||||
|
||||
$this->historyPathname = 'custom/history/modules/' . $moduleName . '/subpanels/' . $subpanelName . '/' . self::HISTORYFILENAME ;
|
||||
$this->_history = new History ( $this->historyPathname ) ;
|
||||
|
||||
$module = get_module_info ( $moduleName ) ;
|
||||
|
||||
require_once ('include/SubPanel/SubPanelDefinitions.php') ;
|
||||
// retrieve the definitions for all the available subpanels for this module from the subpanel
|
||||
$spd = new SubPanelDefinitions ( $module ) ;
|
||||
|
||||
// Get the lists of fields already in the subpanel and those that can be added in
|
||||
// Get the fields lists from an aSubPanel object describing this subpanel from the SubPanelDefinitions object
|
||||
$this->_viewdefs = array ( ) ;
|
||||
$this->_fielddefs = array ( ) ;
|
||||
$this->_language = '' ;
|
||||
if (! empty ( $spd->layout_defs ))
|
||||
if (array_key_exists ( strtolower ( $subpanelName ), $spd->layout_defs [ 'subpanel_setup' ] ))
|
||||
{
|
||||
//First load the original defs from the module folder
|
||||
$originalSubpanel = $spd->load_subpanel( $subpanelName , false, true);
|
||||
$this->_fullFielddefs = $originalSubpanel->get_list_fields ();
|
||||
$this->_mergeFielddefs ( $this->_fielddefs , $this->_fullFielddefs ) ;
|
||||
|
||||
$this->_aSubPanelObject = $spd->load_subpanel ( $subpanelName ) ;
|
||||
// now check if there is a restored subpanel in the history area - if there is, then go ahead and use it
|
||||
if (file_exists ( $this->historyPathname ))
|
||||
{
|
||||
// load in the subpanelDefOverride from the history file
|
||||
$GLOBALS [ 'log' ]->debug ( get_class ( $this ) . ": loading from history" ) ;
|
||||
require $this->historyPathname ;
|
||||
$this->_viewdefs = $layout_defs;
|
||||
} else
|
||||
{
|
||||
$this->_viewdefs = $this->_aSubPanelObject->get_list_fields () ;
|
||||
}
|
||||
|
||||
// don't attempt to access the template_instance property if our subpanel represents a collection, as it won't be there - the sub-sub-panels get this value instead
|
||||
if ( ! $this->_aSubPanelObject->isCollection() )
|
||||
$this->_language = $this->_aSubPanelObject->template_instance->module_dir ;
|
||||
|
||||
// Retrieve a copy of the bean for the parent module of this subpanel - so we can find additional fields for the layout
|
||||
$subPanelParentModuleName = $this->_aSubPanelObject->get_module_name () ;
|
||||
$beanListLower = array_change_key_case ( $GLOBALS [ 'beanList' ] ) ;
|
||||
if (! empty ( $subPanelParentModuleName ) && isset ( $beanListLower [ strtolower ( $subPanelParentModuleName ) ] ))
|
||||
{
|
||||
$subPanelParentModule = get_module_info ( $subPanelParentModuleName ) ;
|
||||
|
||||
// Run through the preliminary list, keeping only those fields that are valid to include in a layout
|
||||
foreach ( $subPanelParentModule->field_defs as $key => $def )
|
||||
{
|
||||
$key = strtolower ( $key ) ;
|
||||
|
||||
if (AbstractMetaDataParser::validField( $def ))
|
||||
{
|
||||
if ( ! isset ( $def [ 'label' ] ) )
|
||||
$def [ 'label' ] = $def [ 'name' ] ;
|
||||
$this->_fielddefs [ $key ] = $def ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->_mergeFielddefs ( $this->_fielddefs , $this->_viewdefs ) ;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function getLanguage ()
|
||||
{
|
||||
return $this->_language ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Save a definition that will be used to display a subpanel for $this->_moduleName
|
||||
* @param array defs Layout definition in the same format as received by the constructor
|
||||
*/
|
||||
function deploy ($defs)
|
||||
{
|
||||
// first sort out the historical record...
|
||||
write_array_to_file ( self::HISTORYVARIABLENAME, $this->_viewdefs, $this->historyPathname, 'w', '' ) ;
|
||||
$this->_history->append ( $this->historyPathname ) ;
|
||||
|
||||
$this->_viewdefs = $defs ;
|
||||
|
||||
require_once 'include/SubPanel/SubPanel.php' ;
|
||||
$subpanel = new SubPanel ( $this->_moduleName, 'fab4', $this->_subpanelName , $this->_aSubPanelObject ) ;
|
||||
|
||||
$subpanel->saveSubPanelDefOverride ( $this->_aSubPanelObject, 'list_fields', $defs ) ;
|
||||
// now clear the cache so that the results are immediately visible
|
||||
include_once ('include/TemplateHandler/TemplateHandler.php') ;
|
||||
TemplateHandler::clearCache ( $this->_moduleName ) ;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
723
modules/ModuleBuilder/parsers/views/GridLayoutMetaDataParser.php
Executable file
723
modules/ModuleBuilder/parsers/views/GridLayoutMetaDataParser.php
Executable file
@@ -0,0 +1,723 @@
|
||||
<?php
|
||||
if (! defined ( 'sugarEntry' ) || ! sugarEntry)
|
||||
die ( 'Not A Valid Entry Point' ) ;
|
||||
/*********************************************************************************
|
||||
* SugarCRM is a customer relationship management program developed by
|
||||
* SugarCRM, Inc. Copyright (C) 2004-2010 SugarCRM Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License version 3 as published by the
|
||||
* Free Software Foundation with the addition of the following permission added
|
||||
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
|
||||
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
|
||||
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License along with
|
||||
* this program; if not, see http://www.gnu.org/licenses or write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA.
|
||||
*
|
||||
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
|
||||
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "Powered by
|
||||
* SugarCRM" logo. If the display of the logo is not reasonably feasible for
|
||||
* technical reasons, the Appropriate Legal Notices must display the words
|
||||
* "Powered by SugarCRM".
|
||||
********************************************************************************/
|
||||
|
||||
require_once 'modules/ModuleBuilder/parsers/views/AbstractMetaDataParser.php' ;
|
||||
require_once 'modules/ModuleBuilder/parsers/views/MetaDataParserInterface.php' ;
|
||||
require_once 'modules/ModuleBuilder/parsers/constants.php' ;
|
||||
|
||||
class GridLayoutMetaDataParser extends AbstractMetaDataParser implements MetaDataParserInterface
|
||||
{
|
||||
|
||||
static $variableMap = array (
|
||||
MB_EDITVIEW => 'EditView' ,
|
||||
MB_DETAILVIEW => 'DetailView' ,
|
||||
MB_QUICKCREATE => 'QuickCreate',
|
||||
) ;
|
||||
|
||||
protected $FILLER ;
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
* @param string view The view type, that is, editview, searchview etc
|
||||
* @param string moduleName The name of the module to which this view belongs
|
||||
* @param string packageName If not empty, the name of the package to which this view belongs
|
||||
*/
|
||||
function __construct ($view , $moduleName , $packageName = '')
|
||||
{
|
||||
$GLOBALS [ 'log' ]->debug ( get_class ( $this ) . "->__construct( {$view} , {$moduleName} , {$packageName} )" ) ;
|
||||
|
||||
$view = strtolower ( $view ) ;
|
||||
|
||||
// BEGIN ASSERTIONS
|
||||
if (! isset ( self::$variableMap [ $view ] ) )
|
||||
sugar_die ( get_class ( $this ) . ": View $view is not supported" ) ;
|
||||
// END ASSERTIONS
|
||||
|
||||
$this->FILLER = array ( 'name' => MBConstants::$FILLER['name'] , 'label' => translate ( MBConstants::$FILLER['label'] ) ) ;
|
||||
|
||||
$this->_moduleName = $moduleName ;
|
||||
$this->_view = $view ;
|
||||
|
||||
if (empty ( $packageName ))
|
||||
{
|
||||
require_once 'modules/ModuleBuilder/parsers/views/DeployedMetaDataImplementation.php' ;
|
||||
$this->implementation = new DeployedMetaDataImplementation ( $view, $moduleName, self::$variableMap ) ;
|
||||
} else
|
||||
{
|
||||
require_once 'modules/ModuleBuilder/parsers/views/UndeployedMetaDataImplementation.php' ;
|
||||
$this->implementation = new UndeployedMetaDataImplementation ( $view, $moduleName, $packageName ) ;
|
||||
}
|
||||
|
||||
$viewdefs = $this->implementation->getViewdefs () ;
|
||||
|
||||
if (! isset ( $viewdefs [ self::$variableMap [ $view ] ] ))
|
||||
sugar_die ( get_class ( $this ) . ": missing variable " . self::$variableMap [ $view ] . " in layout definition" ) ;
|
||||
|
||||
$viewdefs = $viewdefs [ self::$variableMap [ $view ] ] ;
|
||||
if (! isset ( $viewdefs [ 'templateMeta' ] ))
|
||||
sugar_die ( get_class ( $this ) . ": missing templateMeta section in layout definition (case sensitive)" ) ;
|
||||
|
||||
if (! isset ( $viewdefs [ 'panels' ] ))
|
||||
sugar_die ( get_class ( $this ) . ": missing panels section in layout definition (case sensitive)" ) ;
|
||||
|
||||
$this->_viewdefs = $viewdefs ;
|
||||
if ($this->getMaxColumns () < 1)
|
||||
sugar_die ( get_class ( $this ) . ": maxColumns=" . $this->getMaxColumns () . " - must be greater than 0!" ) ;
|
||||
|
||||
$this->_fielddefs = $this->implementation->getFielddefs() ;
|
||||
$this->_standardizeFieldLabels( $this->_fielddefs );
|
||||
$this->_viewdefs [ 'panels' ] = $this->_convertFromCanonicalForm ( $this->_viewdefs [ 'panels' ] , $this->_fielddefs ) ; // put into our internal format
|
||||
$this->_originalViewDef = $this->getFieldsFromLayout($this->implementation->getOriginalViewdefs ());
|
||||
}
|
||||
|
||||
/*
|
||||
* Save a draft layout
|
||||
*/
|
||||
function writeWorkingFile ()
|
||||
{
|
||||
$this->_populateFromRequest ( $this->_fielddefs ) ;
|
||||
$viewdefs = $this->_viewdefs ;
|
||||
$viewdefs [ 'panels' ] = $this->_convertToCanonicalForm ( $this->_viewdefs [ 'panels' ] , $this->_fielddefs ) ;
|
||||
$this->implementation->save ( array ( self::$variableMap [ $this->_view ] => $viewdefs ) ) ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Deploy the layout
|
||||
* @param boolean $populate If true (default), then update the layout first with new layout information from the $_REQUEST array
|
||||
*/
|
||||
function handleSave ($populate = true)
|
||||
{
|
||||
$GLOBALS [ 'log' ]->info ( get_class ( $this ) . "->handleSave()" ) ;
|
||||
|
||||
if ($populate)
|
||||
$this->_populateFromRequest ( $this->_fielddefs ) ;
|
||||
|
||||
$viewdefs = $this->_viewdefs ;
|
||||
$viewdefs [ 'panels' ] = $this->_convertToCanonicalForm ( $this->_viewdefs [ 'panels' ] , $this->_fielddefs ) ;
|
||||
$this->implementation->deploy ( array ( self::$variableMap [ $this->_view ] => $viewdefs ) ) ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the layout, padded out with (empty) and (filler) fields ready for display
|
||||
*/
|
||||
function getLayout ()
|
||||
{
|
||||
$viewdefs = array () ;
|
||||
$fielddefs = $this->_fielddefs;
|
||||
$fielddefs [ $this->FILLER [ 'name' ] ] = $this->FILLER ;
|
||||
$fielddefs [ MBConstants::$EMPTY [ 'name' ] ] = MBConstants::$EMPTY ;
|
||||
|
||||
foreach ( $this->_viewdefs [ 'panels' ] as $panelID => $panel )
|
||||
{
|
||||
foreach ( $panel as $rowID => $row )
|
||||
{
|
||||
foreach ( $row as $colID => $fieldname )
|
||||
{
|
||||
if (isset ($this->_fielddefs [ $fieldname ]))
|
||||
{
|
||||
$viewdefs [ $panelID ] [ $rowID ] [ $colID ] = self::_trimFieldDefs( $this->_fielddefs [ $fieldname ] ) ;
|
||||
}
|
||||
else if (isset($this->_originalViewDef [ $fieldname ]) && is_array($this->_originalViewDef [ $fieldname ]))
|
||||
{
|
||||
$viewdefs [ $panelID ] [ $rowID ] [ $colID ] = self::_trimFieldDefs( $this->_originalViewDef [ $fieldname ] ) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
$viewdefs [ $panelID ] [ $rowID ] [ $colID ] = array("name" => $fieldname, "label" => $fieldname);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $viewdefs ;
|
||||
}
|
||||
|
||||
function getMaxColumns ()
|
||||
{
|
||||
if (!empty( $this->_viewdefs) && isset($this->_viewdefs [ 'templateMeta' ] [ 'maxColumns' ]))
|
||||
{
|
||||
return $this->_viewdefs [ 'templateMeta' ] [ 'maxColumns' ] ;
|
||||
}else
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
function getAvailableFields ()
|
||||
{
|
||||
|
||||
// Obtain the full list of valid fields in this module
|
||||
$availableFields = array () ;
|
||||
foreach ( $this->_fielddefs as $key => $def )
|
||||
{
|
||||
if ( AbstractMetaDataParser::validField ( $def, $this->_view ) || isset($this->_originalViewDef[$key]) )
|
||||
{
|
||||
//If the field original label existing, we should use the original label instead the label in its fielddefs.
|
||||
if(isset($this->_originalViewDef[$key]) && is_array($this->_originalViewDef[$key]) && isset($this->_originalViewDef[$key]['label'])){
|
||||
$availableFields [ $key ] = array ( 'name' => $key , 'label' => $this->_originalViewDef[$key]['label']) ;
|
||||
}else{
|
||||
$availableFields [ $key ] = array ( 'name' => $key , 'label' => isset($def [ 'label' ]) ? $def [ 'label' ] : $def['vname'] ) ; // layouts use 'label' not 'vname' for the label entry
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Available fields are those that are in the Model and the original layout definition, but not already shown in the View
|
||||
// So, because the formats of the two are different we brute force loop through View and unset the fields we find in a copy of Model
|
||||
if (! empty ( $this->_viewdefs ))
|
||||
{
|
||||
foreach ( $this->_viewdefs [ 'panels' ] as $panel )
|
||||
{
|
||||
foreach ( $panel as $row )
|
||||
{
|
||||
foreach ( $row as $field )
|
||||
{
|
||||
unset ( $availableFields [ $field ] ) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $availableFields ;
|
||||
}
|
||||
|
||||
function getPanelDependency ( $panelID )
|
||||
{
|
||||
if ( ! isset ( $this->_viewdefs [ 'templateMeta' ][ 'dependency' ] ) && ! isset ( $this->_viewdefs [ 'templateMeta' ][ 'dependency' ] [ $panelID ] ) )
|
||||
return false;
|
||||
|
||||
return $this->_viewdefs [ 'templateMeta' ][ 'dependency' ] [ $panelID ] ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a new field to the layout
|
||||
* If $panelID is passed in, attempt to add to that panel, otherwise add to the first panel
|
||||
* The field is added in place of the first empty (not filler) slot after the last field in the panel; if that row is full, then a new row will be added to the end of the panel
|
||||
* and the field added to the start of it.
|
||||
* @param array $def Set of properties for the field, in same format as in the viewdefs
|
||||
* @param string $panelID Identifier of the panel to add the field to; empty or false if we should use the first panel
|
||||
*/
|
||||
function addField ( $def , $panelID = FALSE)
|
||||
{
|
||||
|
||||
if (count ( $this->_viewdefs [ 'panels' ] ) == 0)
|
||||
{
|
||||
$GLOBALS [ 'log' ]->error ( get_class ( $this ) . "->addField(): _viewdefs empty for module {$this->_moduleName} and view {$this->_view}" ) ;
|
||||
}
|
||||
|
||||
// if a panelID was not provided, use the first available panel in the list
|
||||
if (! $panelID)
|
||||
{
|
||||
$panels = array_keys ( $this->_viewdefs [ 'panels' ] ) ;
|
||||
list ( $dummy, $panelID ) = each ( $panels ) ;
|
||||
}
|
||||
|
||||
if (isset ( $this->_viewdefs [ 'panels' ] [ $panelID ] ))
|
||||
{
|
||||
|
||||
$panel = $this->_viewdefs [ 'panels' ] [ $panelID ] ;
|
||||
$lastrow = count ( $panel ) - 1 ; // index starts at 0
|
||||
$maxColumns = $this->getMaxColumns () ;
|
||||
for ( $column = 0 ; $column < $maxColumns ; $column ++ )
|
||||
{
|
||||
if (! isset ( $this->_viewdefs [ 'panels' ] [ $panelID ] [ $lastrow ] [ $column ] ) || ($this->_viewdefs [ 'panels' ] [ $panelID ] [ $lastrow ] [ $column ] [ 'name' ] == '(empty)'))
|
||||
break ;
|
||||
}
|
||||
|
||||
// if we're on the last column of the last row, start a new row
|
||||
if ($column >= $maxColumns)
|
||||
{
|
||||
$lastrow ++ ;
|
||||
$this->_viewdefs [ 'panels' ] [ $panelID ] [ $lastrow ] = array ( ) ;
|
||||
$column = 0 ;
|
||||
}
|
||||
|
||||
$this->_viewdefs [ 'panels' ] [ $panelID ] [ $lastrow ] [ $column ] = $def [ 'name' ] ;
|
||||
// now update the fielddefs
|
||||
if (isset($this->_fielddefs [ $def [ 'name' ] ]))
|
||||
{
|
||||
$this->_fielddefs [ $def [ 'name' ] ] = array_merge ( $this->_fielddefs [ $def [ 'name' ] ] , $def ) ;
|
||||
} else
|
||||
{
|
||||
$this->_fielddefs [ $def [ 'name' ] ] = $def;
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove all instances of a field from the layout, and replace by (filler)
|
||||
* Filler because we attempt to preserve the customized layout as much as possible - replacing by (empty) would mean that the positions or sizes of adjacent fields may change
|
||||
* If the last row of a panel only consists of (filler) after removing the fields, then remove the row also. This undoes the standard addField() scenario;
|
||||
* If the fields had been moved around in the layout however then this will not completely undo any addField()
|
||||
* @param string $fieldName Name of the field to remove
|
||||
* @return boolean True if the field was removed; false otherwise
|
||||
*/
|
||||
function removeField ($fieldName)
|
||||
{
|
||||
$GLOBALS [ 'log' ]->info ( get_class ( $this ) . "->removeField($fieldName)" ) ;
|
||||
|
||||
$result = false ;
|
||||
reset ( $this->_viewdefs ) ;
|
||||
$firstPanel = each ( $this->_viewdefs [ 'panels' ] ) ;
|
||||
$firstPanelID = $firstPanel [ 'key' ] ;
|
||||
|
||||
foreach ( $this->_viewdefs [ 'panels' ] as $panelID => $panel )
|
||||
{
|
||||
$lastRowTouched = false ;
|
||||
$lastRowID = count ( $this->_viewdefs [ 'panels' ] [ $panelID ] ) - 1 ; // zero offset
|
||||
|
||||
foreach ( $panel as $rowID => $row )
|
||||
{
|
||||
|
||||
foreach ( $row as $colID => $field )
|
||||
if ($field == $fieldName)
|
||||
{
|
||||
$lastRowTouched = $rowID ;
|
||||
$this->_viewdefs [ 'panels' ] [ $panelID ] [ $rowID ] [ $colID ] = $this->FILLER [ 'name' ];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// if we removed a field from the last row of this panel, tidy up if the last row now consists only of (empty) or (filler)
|
||||
|
||||
if ( $lastRowTouched == $lastRowID )
|
||||
{
|
||||
$lastRow = $this->_viewdefs [ 'panels' ] [ $panelID ] [ $lastRowID ] ; // can't use 'end' for this as we need the key as well as the value...
|
||||
|
||||
$empty = true ;
|
||||
|
||||
foreach ( $lastRow as $colID => $field )
|
||||
$empty &= $field == MBConstants::$EMPTY ['name' ] || $field == $this->FILLER [ 'name' ] ;
|
||||
|
||||
if ($empty)
|
||||
{
|
||||
unset ( $this->_viewdefs [ 'panels' ] [ $panelID ] [ $lastRowID ] ) ;
|
||||
// if the row was the only one in the panel, and the panel is not the first (default) panel, then remove the panel also
|
||||
if ( count ( $this->_viewdefs [ 'panels' ] [ $panelID ] ) == 0 && $panelID != $firstPanelID )
|
||||
unset ( $this->_viewdefs [ 'panels' ] [ $panelID ] ) ;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$result |= ($lastRowTouched !== false ); // explicitly compare to false as row 0 will otherwise evaluate as false
|
||||
}
|
||||
|
||||
return $result ;
|
||||
|
||||
}
|
||||
|
||||
function setPanelDependency ( $panelID , $dependency )
|
||||
{
|
||||
// only accept dependencies for pre-existing panels
|
||||
if ( ! isset ( $this->_viewdefs [ 'panels' ] [ $panelID ] ) )
|
||||
return false;
|
||||
|
||||
$this->_viewdefs [ 'templateMeta' ] [ 'dependency' ] [ $panelID ] = $dependency ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return an integer value for the next unused panel identifier, such that it and any larger numbers are guaranteed to be unused already in the layout
|
||||
* Necessary when adding new panels to a layout
|
||||
* @return integer First unique panel ID suffix
|
||||
*/
|
||||
function getFirstNewPanelId ()
|
||||
{
|
||||
$firstNewPanelId = 0 ;
|
||||
foreach ( $this->_viewdefs [ 'panels' ] as $panelID => $panel )
|
||||
{
|
||||
// strip out all but the numerics from the panelID - can't just use a cast as numbers may not be first in the string
|
||||
for ( $i = 0, $result = '' ; $i < strlen ( $panelID ) ; $i ++ )
|
||||
{
|
||||
if (is_numeric ( $panelID [ $i ] ))
|
||||
{
|
||||
$result .= $panelID [ $i ] ;
|
||||
}
|
||||
}
|
||||
|
||||
$firstNewPanelId = max ( ( int ) $result, $firstNewPanelId ) ;
|
||||
}
|
||||
return $firstNewPanelId + 1 ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Load the panel layout from the submitted form and update the _viewdefs
|
||||
*/
|
||||
protected function _populateFromRequest ( &$fielddefs )
|
||||
{
|
||||
$GLOBALS [ 'log' ]->debug ( get_class ( $this ) . "->populateFromRequest()" ) ;
|
||||
$i = 1 ;
|
||||
|
||||
// set up the map of panel# (as provided in the _REQUEST) to panel ID (as used in $this->_viewdefs['panels'])
|
||||
$i = 1 ;
|
||||
foreach ( $this->_viewdefs [ 'panels' ] as $panelID => $panel )
|
||||
{
|
||||
$panelMap [ $i ++ ] = $panelID ;
|
||||
}
|
||||
|
||||
foreach ( $_REQUEST as $key => $displayLabel )
|
||||
{
|
||||
$components = explode ( '-', $key ) ;
|
||||
if ($components [ 0 ] == 'panel' && $components [ 2 ] == 'label')
|
||||
{
|
||||
$panelMap [ $components [ '1' ] ] = $displayLabel ;
|
||||
}
|
||||
}
|
||||
|
||||
$this->_viewdefs [ 'panels' ] = array () ; // because the new field properties should replace the old fields, not be merged
|
||||
|
||||
// run through the $_REQUEST twice - first to obtain the fieldnames, the second to update the field properties
|
||||
for ( $pass=1 ; $pass<=2 ; $pass++ )
|
||||
{
|
||||
foreach ( $_REQUEST as $slot => $value )
|
||||
{
|
||||
$slotComponents = explode ( '-', $slot ) ; // [0] = 'slot', [1] = panel #, [2] = slot #, [3] = property name
|
||||
|
||||
if ($slotComponents [ 0 ] == 'slot')
|
||||
{
|
||||
$slotNumber = $slotComponents [ '2' ] ;
|
||||
$panelID = $panelMap [ $slotComponents [ '1' ] ] ;
|
||||
$rowID = floor ( $slotNumber / $this->getMaxColumns () ) ;
|
||||
$colID = $slotNumber - ($rowID * $this->getMaxColumns ()) ;
|
||||
$property = $slotComponents [ '3' ] ;
|
||||
|
||||
//If this field has a custom definition, copy that over
|
||||
if ( $pass == 1 )
|
||||
{
|
||||
if ( $property == 'name' )
|
||||
$this->_viewdefs [ 'panels' ] [ $panelID ] [ $rowID ] [ $colID ] = $value ;
|
||||
} else
|
||||
{
|
||||
// update fielddefs for this property in the provided position
|
||||
if ( isset ( $this->_viewdefs [ 'panels' ] [ $panelID ] [ $rowID ] [ $colID ] ) )
|
||||
{
|
||||
$fieldname = $this->_viewdefs [ 'panels' ] [ $panelID ] [ $rowID ] [ $colID ] ;
|
||||
$fielddefs [ $fieldname ] [ $property ] = $value ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//Set the tabs setting
|
||||
if (isset($_REQUEST['panels_as_tabs']))
|
||||
{
|
||||
if ($_REQUEST['panels_as_tabs'] == false || $_REQUEST['panels_as_tabs'] == "false")
|
||||
$this->setUseTabs( false );
|
||||
else
|
||||
$this->setUseTabs( true );
|
||||
}
|
||||
|
||||
$GLOBALS [ 'log' ]->debug ( print_r ( $this->_viewdefs [ 'panels' ], true ) ) ;
|
||||
|
||||
}
|
||||
|
||||
/* Convert our internal format back to the standard Canonical MetaData layout
|
||||
* First non-(empty) field goes in at column 0; all other (empty)'s removed
|
||||
* Studio required fields are also added to the layout.
|
||||
* Do this AFTER reading in all the $_REQUEST parameters as can't guarantee the order of those, and we need to operate on complete rows
|
||||
*/
|
||||
protected function _convertToCanonicalForm ( $panels , $fielddefs )
|
||||
{
|
||||
$previousViewDef = $this->getFieldsFromLayout($this->implementation->getViewdefs ());
|
||||
$oldDefs = $this->implementation->getViewdefs ();
|
||||
$currentFields = $this->getFieldsFromLayout($this->_viewdefs);
|
||||
foreach($fielddefs as $field => $def)
|
||||
{
|
||||
if (self::fieldIsRequired($def) && !isset($currentFields[$field]))
|
||||
{
|
||||
//Use the previous viewdef if this field was on it.
|
||||
if (isset($previousViewDef[$field]))
|
||||
{
|
||||
$def = $previousViewDef[$field];
|
||||
}
|
||||
//next see if the field was on the original layout.
|
||||
else if (isset ($this->_originalViewDef [ $field ]))
|
||||
{
|
||||
$def = $this->_originalViewDef [ $field ] ;
|
||||
}
|
||||
//Otherwise make up a viewdef for it from field_defs
|
||||
else
|
||||
{
|
||||
$def = self::_trimFieldDefs( $def ) ;
|
||||
}
|
||||
$this->addField($def);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ( $panels as $panelID => $panel )
|
||||
{
|
||||
// remove all (empty)s
|
||||
foreach ( $panel as $rowID => $row )
|
||||
{
|
||||
$startOfRow = true ;
|
||||
$offset = 0 ;
|
||||
foreach ( $row as $colID => $fieldname )
|
||||
{
|
||||
if ($fieldname == MBConstants::$EMPTY[ 'name' ])
|
||||
{
|
||||
// if a leading (empty) then remove (by noting that remaining fields need to be shuffled along)
|
||||
if ($startOfRow)
|
||||
{
|
||||
$offset ++ ;
|
||||
}
|
||||
unset ( $row [ $colID ] ) ;
|
||||
} else
|
||||
{
|
||||
$startOfRow = false ;
|
||||
}
|
||||
}
|
||||
|
||||
// reindex to remove leading (empty)s and replace fieldnames by full definition from fielddefs
|
||||
$newRow = array ( ) ;
|
||||
foreach ( $row as $colID => $fieldname )
|
||||
{
|
||||
if ($fieldname == null)
|
||||
continue;
|
||||
|
||||
//Backwards compatibility and a safeguard against multiple calls to _convertToCanonicalForm
|
||||
if(is_array($fieldname))
|
||||
{
|
||||
$newRow [ $colID - $offset ] = $fieldname;
|
||||
continue;
|
||||
}
|
||||
|
||||
//Replace (filler) with the empty string
|
||||
if ($fieldname == $this->FILLER[ 'name' ]) {
|
||||
$newRow [ $colID - $offset ] = '' ;
|
||||
}
|
||||
//Use the previous viewdef if this field was on it.
|
||||
else if (isset($previousViewDef[$fieldname]))
|
||||
{
|
||||
$newRow [ $colID - $offset ] = $previousViewDef[$fieldname];
|
||||
//We should copy over the tabindex if it is set.
|
||||
if (isset ($fielddefs [ $fieldname ]) && !empty($fielddefs [ $fieldname ]['tabindex']))
|
||||
$newRow [ $colID - $offset ]['tabindex'] = $fielddefs [ $fieldname ]['tabindex'];
|
||||
}
|
||||
//next see if the field was on the original layout.
|
||||
else if (isset ($this->_originalViewDef [ $fieldname ]))
|
||||
{
|
||||
$newRow [ $colID - $offset ] = $this->_originalViewDef [ $fieldname ] ;
|
||||
//We should copy over the tabindex if it is set.
|
||||
if (isset ($fielddefs [ $fieldname ]) && !empty($fielddefs [ $fieldname ]['tabindex']))
|
||||
$newRow [ $colID - $offset ]['tabindex'] = $fielddefs [ $fieldname ]['tabindex'];
|
||||
}
|
||||
//Otherwise make up a viewdef for it from field_defs
|
||||
else if (isset ($fielddefs [ $fieldname ]))
|
||||
{
|
||||
$newRow [ $colID - $offset ] = self::_trimFieldDefs( $fielddefs [ $fieldname ] ) ;
|
||||
|
||||
}
|
||||
//No additional info on this field can be found, jsut use the name;
|
||||
else
|
||||
{
|
||||
$newRow [ $colID - $offset ] = $fieldname;
|
||||
}
|
||||
}
|
||||
$panels [ $panelID ] [ $rowID ] = $newRow ;
|
||||
}
|
||||
}
|
||||
|
||||
return $panels ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert from the standard MetaData format to our internal format
|
||||
* Replace NULL with (filler) and missing entries with (empty)
|
||||
*/
|
||||
protected function _convertFromCanonicalForm ( $panels , $fielddefs )
|
||||
{
|
||||
if (empty ( $panels ))
|
||||
return ;
|
||||
|
||||
// Fix for a flexibility in the format of the panel sections - if only one panel, then we don't have a panel level defined,
|
||||
// it goes straight into rows
|
||||
// See EditView2 for similar treatment
|
||||
if (! empty ( $panels ) && count ( $panels ) > 0)
|
||||
{
|
||||
$keys = array_keys ( $panels ) ;
|
||||
if (is_numeric ( $keys [ 0 ] ))
|
||||
{
|
||||
$defaultPanel = $panels ;
|
||||
unset ( $panels ) ; //blow away current value
|
||||
$panels [ 'default' ] = $defaultPanel ;
|
||||
}
|
||||
}
|
||||
|
||||
$newPanels = array ( ) ;
|
||||
|
||||
// replace '' with (filler)
|
||||
foreach ( $panels as $panelID => $panel )
|
||||
{
|
||||
foreach ( $panel as $rowID => $row )
|
||||
{
|
||||
$cols = 0;
|
||||
foreach ( $row as $colID => $col )
|
||||
{
|
||||
if ( ! empty ( $col ) )
|
||||
{
|
||||
if ( is_string ( $col ))
|
||||
{
|
||||
$fieldname = $col ;
|
||||
} else if (! empty ( $col [ 'name' ] ))
|
||||
{
|
||||
$fieldname = $col [ 'name' ] ;
|
||||
}
|
||||
} else
|
||||
{
|
||||
$fieldname = $this->FILLER['name'] ;
|
||||
}
|
||||
|
||||
$newPanels [ $panelID ] [ $rowID ] [ $cols ] = $fieldname ;
|
||||
$cols++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// replace missing fields with (empty)
|
||||
foreach ( $newPanels as $panelID => $panel )
|
||||
{
|
||||
$column = 0 ;
|
||||
foreach ( $panel as $rowID => $row )
|
||||
{
|
||||
// pad between fields on a row
|
||||
foreach ( $row as $colID => $col )
|
||||
{
|
||||
for ( $i = $column + 1 ; $i < $colID ; $i ++ )
|
||||
{
|
||||
$row [ $i ] = MBConstants::$EMPTY ['name'];
|
||||
}
|
||||
$column = $colID ;
|
||||
}
|
||||
// now pad out to the end of the row
|
||||
if (($column + 1) < $this->getMaxColumns ())
|
||||
{ // last column is maxColumns-1
|
||||
for ( $i = $column + 1 ; $i < $this->getMaxColumns () ; $i ++ )
|
||||
{
|
||||
$row [ $i ] = MBConstants::$EMPTY ['name'] ;
|
||||
}
|
||||
}
|
||||
ksort ( $row ) ;
|
||||
$newPanels [ $panelID ] [ $rowID ] = $row ;
|
||||
}
|
||||
}
|
||||
|
||||
return $newPanels ;
|
||||
}
|
||||
|
||||
protected function getFieldsFromLayout($viewdef) {
|
||||
if (isset($viewdef['panels']))
|
||||
{
|
||||
$panels = $viewdef['panels'];
|
||||
} else {
|
||||
$panels = $viewdef[self::$variableMap [ $this->_view ] ]['panels'];
|
||||
}
|
||||
|
||||
$ret = array();
|
||||
if (is_array($panels))
|
||||
{
|
||||
foreach ( $panels as $rows) {
|
||||
foreach ($rows as $fields) {
|
||||
//wireless layouts have one less level of depth
|
||||
if (is_array($fields) && isset($fields['name'])) {
|
||||
$ret[$fields['name']] = $fields;
|
||||
continue;
|
||||
}
|
||||
if (!is_array($fields)) {
|
||||
$ret[$fields] = $fields;
|
||||
continue;
|
||||
}
|
||||
foreach ($fields as $field) {
|
||||
if (is_array($field) && !empty($field['name']))
|
||||
{
|
||||
$ret[$field['name']] = $field;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
protected function fieldIsRequired($def)
|
||||
{
|
||||
if (isset($def['studio']))
|
||||
{
|
||||
if (is_array($def['studio']))
|
||||
{
|
||||
if (!empty($def['studio'][$this->_view]) && $def['studio'][$this->_view] == "required")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (!empty($def['studio']['required']) && $def['studio']['required'] == true)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if ($def['studio'] == "required" ){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static function _trimFieldDefs ( $def )
|
||||
{
|
||||
$ret = array_intersect_key ( $def ,
|
||||
array ( 'studio' => true , 'name' => true , 'label' => true , 'displayParams' => true , 'comment' => true ,
|
||||
'customCode' => true , 'customLabel' => true , 'tabIndex' => true , 'hideLabel' => true) ) ;
|
||||
if (!empty($def['vname']) && empty($def['label']))
|
||||
$ret['label'] = $def['vname'];
|
||||
return $ret;
|
||||
}
|
||||
|
||||
public function getUseTabs(){
|
||||
if (isset($this->_viewdefs [ 'templateMeta' ]['useTabs']))
|
||||
return $this->_viewdefs [ 'templateMeta' ]['useTabs'];
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function setUseTabs($useTabs){
|
||||
$this->_viewdefs [ 'templateMeta' ]['useTabs'] = $useTabs;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
218
modules/ModuleBuilder/parsers/views/History.php
Executable file
218
modules/ModuleBuilder/parsers/views/History.php
Executable file
@@ -0,0 +1,218 @@
|
||||
<?php
|
||||
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
|
||||
/*********************************************************************************
|
||||
* SugarCRM is a customer relationship management program developed by
|
||||
* SugarCRM, Inc. Copyright (C) 2004-2010 SugarCRM Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License version 3 as published by the
|
||||
* Free Software Foundation with the addition of the following permission added
|
||||
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
|
||||
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
|
||||
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License along with
|
||||
* this program; if not, see http://www.gnu.org/licenses or write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA.
|
||||
*
|
||||
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
|
||||
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "Powered by
|
||||
* SugarCRM" logo. If the display of the logo is not reasonably feasible for
|
||||
* technical reasons, the Appropriate Legal Notices must display the words
|
||||
* "Powered by SugarCRM".
|
||||
********************************************************************************/
|
||||
|
||||
require_once 'modules/ModuleBuilder/parsers/constants.php' ;
|
||||
|
||||
class History
|
||||
{
|
||||
|
||||
private $_dirname ; // base directory for the history files
|
||||
private $_basename ; // base name for a history file, for example, listviewdef.php
|
||||
private $_list ; // the history - a list of history files
|
||||
|
||||
private $_previewFilename ; // the location of a file for preview
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
* @param string $previewFilename The filename which the caller expects for a preview file
|
||||
*/
|
||||
function __construct ($previewFilename )
|
||||
{
|
||||
$GLOBALS [ 'log' ]->debug ( get_class ( $this ) . "->__construct( {$previewFilename} )" ) ;
|
||||
$this->_previewFilename = $previewFilename ;
|
||||
$this->_list = array ( ) ;
|
||||
|
||||
$this->_dirname = dirname ( $this->_previewFilename ) ;
|
||||
// create the history directory if it does not already exist
|
||||
if (! is_dir ( $this->_dirname ))
|
||||
{
|
||||
mkdir_recursive ( $this->_dirname ) ;
|
||||
}
|
||||
$this->_basename = basename ( $this->_previewFilename ) ;
|
||||
// Reconstruct the history from the saved files
|
||||
foreach ( scandir ( $this->_dirname ) as $filename )
|
||||
{
|
||||
if ($filename != "." && $filename != "..")
|
||||
{
|
||||
// history files are of the form {$basename}_{$timestamp}
|
||||
if (preg_match ( '/(' . $this->_basename . ')_(.*)/', $filename, $matches ) == 1)
|
||||
{
|
||||
$this->_list [ $matches [ 2 ] ] = $matches [ 2 ] ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// now sort the files, oldest first
|
||||
if (count ( $this->_list ) > 0)
|
||||
{
|
||||
ksort ( $this->_list ) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get the most recent item in the history
|
||||
* @return timestamp of the first item
|
||||
*/
|
||||
function getCount ()
|
||||
{
|
||||
return count ( $this->_list ) ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the most recent item in the history
|
||||
* @return timestamp of the first item
|
||||
*/
|
||||
function getFirst ()
|
||||
{
|
||||
return end ( $this->_list ) ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the oldest item in the history (the default layout)
|
||||
* @return timestamp of the last item
|
||||
*/
|
||||
function getLast ()
|
||||
{
|
||||
return reset ( $this->_list ) ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the next oldest item in the history
|
||||
* @return timestamp of the next item
|
||||
*/
|
||||
function getNext ()
|
||||
{
|
||||
return prev ( $this->_list ) ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the nth item in the history (where the zeroeth record is the most recent)
|
||||
* @return timestamp of the nth item
|
||||
*/
|
||||
function getNth ($index)
|
||||
{
|
||||
$value = end ( $this->_list ) ;
|
||||
$i = 0 ;
|
||||
while ( $i < $index )
|
||||
{
|
||||
$value = prev ( $this->_list ) ;
|
||||
$i ++ ;
|
||||
}
|
||||
return $value ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add an item to the history
|
||||
* @return String A GMT Unix timestamp for this newly added item
|
||||
*/
|
||||
function append ($path)
|
||||
{
|
||||
// make sure we don't have a duplicate filename - highly unusual as two people should not be using Studio/MB concurrently, but when testing quite possible to do two appends within one second...
|
||||
// because so unlikely in normal use we handle this the naive way by waiting a second so our naming scheme doesn't get overelaborated
|
||||
$retries = 0 ;
|
||||
|
||||
$time = strtotime ( gmdate ( 'r' ) ) ;
|
||||
while ( (file_exists ( $this->_previewFilename . "_" . $time ) && $retries < 5) )
|
||||
|
||||
{
|
||||
sleep ( 1 ) ;
|
||||
$time = strtotime ( gmdate ( 'r' ) ) ;
|
||||
$retries ++ ;
|
||||
}
|
||||
// now we have a unique filename, copy the file into the history
|
||||
copy ( $path, $this->_previewFilename . "_" . $time ) ;
|
||||
$this->_list [ $time ] = $time ;
|
||||
|
||||
// finally, trim the number of files we're holding in the history to that specified in the configuration
|
||||
$max_history = (isset ( $GLOBALS [ 'sugar_config' ] [ 'studio_max_history' ] )) ? $GLOBALS [ 'sugar_config' ] [ 'studio_max_history' ] : 50 ;
|
||||
$count = count ( $this->_list ) ;
|
||||
// truncate the oldest files, keeping only the most recent $GLOBALS['sugar_config']['studio_max_history'] files (zero=keep them all)
|
||||
if (($max_history != 0) && ($count > $max_history))
|
||||
{
|
||||
// most recent files are at the end of the list, so we strip out the first count-max_history records
|
||||
// can't just use array_shift because it renumbers numeric keys (our timestamp keys) to start from zero...
|
||||
for ( $i = 0 ; $i < $count - $max_history ; $i ++ )
|
||||
{
|
||||
$timestamp = reset ( $this->_list ) ;
|
||||
unset ( $this->_list [ $timestamp ] ) ;
|
||||
if (! unlink ( $this->_dirname . "/" . $this->_basename . "_" . $timestamp ))
|
||||
{
|
||||
$GLOBALS [ 'log' ]->warn ( "History.php: unable to remove history file {$this->_basename}_$timestamp from directory {$this->_dirname} - permissions problem?" ) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// finally, remove any history preview file that might be lurking around - as soon as we append a new record it supercedes any old preview, so that must be removed (bug 20130)
|
||||
if (file_exists($this->_previewFilename))
|
||||
{
|
||||
$GLOBALS [ 'log' ]->debug( get_class($this)."->append(): removing old history file at {$this->_previewFilename}");
|
||||
unlink ( $this->_previewFilename);
|
||||
}
|
||||
|
||||
return $time ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Restore the historical layout identified by timestamp
|
||||
* @param Unix timestamp $timestamp GMT Timestamp of the layout to recover
|
||||
* @return GMT Timestamp if successful, null if failure (if the file could not be copied for some reason)
|
||||
*/
|
||||
function restoreByTimestamp ($timestamp)
|
||||
{
|
||||
$filename = $this->_previewFilename . "_" . $timestamp ;
|
||||
$GLOBALS [ 'log' ]->debug ( get_class ( $this ) . ": restoring from $filename to {$this->_previewFilename}" ) ;
|
||||
|
||||
if (file_exists ( $filename ))
|
||||
{
|
||||
copy ( $filename, $this->_previewFilename ) ;
|
||||
return $timestamp ;
|
||||
}
|
||||
return null ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Undo the restore - revert back to the layout before the restore
|
||||
*/
|
||||
function undoRestore ()
|
||||
{
|
||||
if (file_exists ( $this->_previewFilename ))
|
||||
{
|
||||
unlink ( $this->_previewFilename ) ;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
75
modules/ModuleBuilder/parsers/views/HistoryInterface.php
Executable file
75
modules/ModuleBuilder/parsers/views/HistoryInterface.php
Executable file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
|
||||
/*********************************************************************************
|
||||
* SugarCRM is a customer relationship management program developed by
|
||||
* SugarCRM, Inc. Copyright (C) 2004-2010 SugarCRM Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License version 3 as published by the
|
||||
* Free Software Foundation with the addition of the following permission added
|
||||
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
|
||||
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
|
||||
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License along with
|
||||
* this program; if not, see http://www.gnu.org/licenses or write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA.
|
||||
*
|
||||
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
|
||||
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "Powered by
|
||||
* SugarCRM" logo. If the display of the logo is not reasonably feasible for
|
||||
* technical reasons, the Appropriate Legal Notices must display the words
|
||||
* "Powered by SugarCRM".
|
||||
********************************************************************************/
|
||||
|
||||
interface HistoryInterface
|
||||
{
|
||||
|
||||
/*
|
||||
* Get the most recent item in the history
|
||||
* @return Id of the first item
|
||||
*/
|
||||
function getFirst () ;
|
||||
|
||||
/*
|
||||
* Get the next oldest item in the history
|
||||
* @return Id of the next item
|
||||
*/
|
||||
function getNext () ;
|
||||
|
||||
/*
|
||||
* Get the nth item in the history (where the zeroeth record is the most recent)
|
||||
* @return Id of the nth item
|
||||
*/
|
||||
function getNth ($n) ;
|
||||
|
||||
/*
|
||||
* Restore the historical layout identified by timestamp
|
||||
* @return Timestamp if successful, null if failure (if the file could not be copied for some reason)
|
||||
*/
|
||||
function restoreByTimestamp ($timestamp) ;
|
||||
|
||||
/*
|
||||
* Undo the restore - revert back to the layout before the restore
|
||||
*/
|
||||
function undoRestore () ;
|
||||
|
||||
/*
|
||||
* Add an item to the history
|
||||
* @return String An timestamp for this newly added item
|
||||
*/
|
||||
function append ($path) ;
|
||||
}
|
||||
361
modules/ModuleBuilder/parsers/views/ListLayoutMetaDataParser.php
Executable file
361
modules/ModuleBuilder/parsers/views/ListLayoutMetaDataParser.php
Executable file
@@ -0,0 +1,361 @@
|
||||
<?php
|
||||
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
|
||||
/*********************************************************************************
|
||||
* SugarCRM is a customer relationship management program developed by
|
||||
* SugarCRM, Inc. Copyright (C) 2004-2010 SugarCRM Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License version 3 as published by the
|
||||
* Free Software Foundation with the addition of the following permission added
|
||||
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
|
||||
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
|
||||
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License along with
|
||||
* this program; if not, see http://www.gnu.org/licenses or write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA.
|
||||
*
|
||||
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
|
||||
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "Powered by
|
||||
* SugarCRM" logo. If the display of the logo is not reasonably feasible for
|
||||
* technical reasons, the Appropriate Legal Notices must display the words
|
||||
* "Powered by SugarCRM".
|
||||
********************************************************************************/
|
||||
|
||||
require_once 'modules/ModuleBuilder/parsers/views/AbstractMetaDataParser.php' ;
|
||||
require_once 'modules/ModuleBuilder/parsers/views/MetaDataParserInterface.php' ;
|
||||
|
||||
class ListLayoutMetaDataParser extends AbstractMetaDataParser implements MetaDataParserInterface
|
||||
{
|
||||
|
||||
// Columns is used by the view to construct the listview - each column is built by calling the named function
|
||||
public $columns = array ( 'LBL_DEFAULT' => 'getDefaultFields' , 'LBL_AVAILABLE' => 'getAdditionalFields' , 'LBL_HIDDEN' => 'getAvailableFields' ) ;
|
||||
protected $labelIdentifier = 'label' ; // labels in the listviewdefs.php are tagged 'label' =>
|
||||
protected $allowParent = false;
|
||||
|
||||
/*
|
||||
* Simple function for array_udiff_assoc function call in getAvailableFields()
|
||||
*/
|
||||
static function getArrayDiff ($one , $two)
|
||||
{
|
||||
$retArray = array();
|
||||
foreach($one as $key => $value)
|
||||
{
|
||||
if (!isset($two[$key]))
|
||||
{
|
||||
$retArray[$key] = $value;
|
||||
}
|
||||
}
|
||||
return $retArray;
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
* @param string view The view type, that is, editview, searchview etc
|
||||
* @param string moduleName The name of the module to which this listview belongs
|
||||
* @param string packageName If not empty, the name of the package to which this listview belongs
|
||||
*/
|
||||
function __construct ($view , $moduleName , $packageName = '')
|
||||
{
|
||||
$GLOBALS [ 'log' ]->debug ( get_class ( $this ) . ": __construct()" ) ;
|
||||
|
||||
// BEGIN ASSERTIONS
|
||||
$views = array ( MB_LISTVIEW, MB_DASHLET, MB_DASHLETSEARCH, MB_POPUPLIST, MB_POPUPSEARCH ) ;
|
||||
if (! in_array ( $view , $views ) )
|
||||
{
|
||||
sugar_die ( "ListLayoutMetaDataParser: View $view is not supported" ) ;
|
||||
}
|
||||
// END ASSERTIONS
|
||||
|
||||
if (empty ( $packageName ))
|
||||
{
|
||||
require_once 'modules/ModuleBuilder/parsers/views/DeployedMetaDataImplementation.php' ;
|
||||
$this->implementation = new DeployedMetaDataImplementation ( $view, $moduleName ) ;
|
||||
} else
|
||||
{
|
||||
require_once 'modules/ModuleBuilder/parsers/views/UndeployedMetaDataImplementation.php' ;
|
||||
$this->implementation = new UndeployedMetaDataImplementation ( $view, $moduleName, $packageName ) ;
|
||||
}
|
||||
$this->view = $view;
|
||||
|
||||
$this->_fielddefs = $this->implementation->getFielddefs () ;
|
||||
$this->_standardizeFieldLabels( $this->_fielddefs );
|
||||
$this->_viewdefs = array_change_key_case ( $this->implementation->getViewdefs () ) ; // force to lower case so don't have problems with case mismatches later
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Deploy the layout
|
||||
* @param boolean $populate If true (default), then update the layout first with new layout information from the $_REQUEST array
|
||||
*/
|
||||
function handleSave ($populate = true)
|
||||
{
|
||||
if ($populate)
|
||||
$this->_populateFromRequest () ;
|
||||
$this->implementation->deploy ( array_change_key_case ( $this->_viewdefs, CASE_UPPER ) ) ; // force the field names back to upper case so the list view will work correctly
|
||||
}
|
||||
|
||||
function getLayout ()
|
||||
{
|
||||
return $this->_viewdefs ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of the default fields for a listview
|
||||
* @return array List of default fields as an array, where key = value = <field name>
|
||||
*/
|
||||
function getDefaultFields ()
|
||||
{
|
||||
$defaultFields = array ( ) ;
|
||||
foreach ( $this->_viewdefs as $key => $def )
|
||||
{
|
||||
// add in the default fields from the listviewdefs but hide fields disabled in the listviewdefs.
|
||||
if (! empty ( $def [ 'default' ] )
|
||||
&& (!isset($def [ 'studio' ]) || ($def [ 'studio' ] !== false && $def [ 'studio' ] != "false")))
|
||||
{
|
||||
if (isset($this->_fielddefs [ $key ] )) {
|
||||
$defaultFields [ $key ] = self::_trimFieldDefs ( $this->_fielddefs [ $key ] ) ;
|
||||
if (!empty($def['label']))
|
||||
$defaultFields [ $key ]['label'] = $def['label'];
|
||||
}
|
||||
else {
|
||||
$defaultFields [ $key ] = $def;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $defaultFields ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns additional fields available for users to create fields
|
||||
@return array List of additional fields as an array, where key = value = <field name>
|
||||
*/
|
||||
function getAdditionalFields ()
|
||||
{
|
||||
$additionalFields = array ( ) ;
|
||||
foreach ( $this->_viewdefs as $key => $def )
|
||||
{
|
||||
//#25322
|
||||
if(strtolower ( $key ) == 'email_opt_out'){
|
||||
continue;
|
||||
}
|
||||
|
||||
if (empty ( $def [ 'default' ] ))
|
||||
{
|
||||
if (isset($this->_fielddefs [ $key ] ))
|
||||
$additionalFields [ $key ] = self::_trimFieldDefs ( $this->_fielddefs [ $key ] ) ;
|
||||
else
|
||||
$additionalFields [ $key ] = $def;
|
||||
}
|
||||
}
|
||||
return $additionalFields ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns unused fields that are available for use in either default or additional list views
|
||||
* @return array List of available fields as an array, where key = value = <field name>
|
||||
*/
|
||||
function getAvailableFields ()
|
||||
{
|
||||
$availableFields = array ( ) ;
|
||||
// Select available fields from the field definitions - don't need to worry about checking if ok to include as the Implementation has done that already in its constructor
|
||||
foreach ( $this->_fielddefs as $key => $def )
|
||||
{
|
||||
if ($this->isValidField($key, $def))
|
||||
$availableFields [ $key ] = self::_trimFieldDefs( $this->_fielddefs [ $key ] ) ;
|
||||
|
||||
$origDefs = $this->getOriginalViewDefs();
|
||||
foreach($origDefs as $key => $def)
|
||||
{
|
||||
$availableFields [ $key ] = $def;
|
||||
}
|
||||
}
|
||||
|
||||
//$GLOBALS['log']->debug(get_class($this).'->getAvailableFields(): '.print_r($availableFields,true));
|
||||
// now remove all fields that are already in the viewdef - they are not available; they are in use
|
||||
return ListLayoutMetaDataParser::getArrayDiff ( $availableFields, $this->_viewdefs) ;
|
||||
}
|
||||
|
||||
public function isValidField($key, $def)
|
||||
{
|
||||
//Studio invisible fields should always be hidden
|
||||
if (! empty ($def[ 'studio' ] ) )
|
||||
{
|
||||
if (is_array($def [ 'studio' ]))
|
||||
{
|
||||
if (isset($def [ 'studio' ]['listview']))
|
||||
return $def [ 'studio' ]['listview'] !== false && $def [ 'studio' ]['listview'] != 'false';
|
||||
if (isset($def [ 'studio' ]['visible']))
|
||||
return $def [ 'studio' ]['visible'];
|
||||
} else
|
||||
{
|
||||
return ($def [ 'studio' ] != 'false' && $def [ 'studio' ] !== false && $def [ 'studio' ] != 'hidden') ;
|
||||
}
|
||||
}
|
||||
|
||||
//Bug 32520. We need to dissalow currency_id fields on list views.
|
||||
//This should be removed once array based studio definitions are in.
|
||||
if (isset($def['type']) && $def['type'] == "id" && $def['name'] == 'currency_id')
|
||||
return false;
|
||||
|
||||
//Check fields types
|
||||
if (isset($def['dbType']) && $def['dbType'] == "id")
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isset($def['type']))
|
||||
{
|
||||
if ($def['type'] == 'html' || ($def['type'] == 'parent' && !$this->allowParent)
|
||||
|| $def['type'] == "id" || $def['type'] == "link" || $def['type'] == 'image')
|
||||
return false;
|
||||
}
|
||||
|
||||
//hide currency_id, deleted, and _name fields by key-name
|
||||
if(strcmp ( $key, 'deleted' ) == 0 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//if all the tests failed, the field is probably ok
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function _populateFromRequest ()
|
||||
{
|
||||
$GLOBALS [ 'log' ]->debug ( get_class ( $this ) . "->populateFromRequest() - fielddefs = ".print_r($this->_fielddefs, true));
|
||||
// Transfer across any reserved fields, that is, any where studio !== true, which are not editable but must be preserved
|
||||
$newViewdefs = array ( ) ;
|
||||
$rejectTypes = array ( 'html'=>'html' , 'enum'=>'enum' , 'text'=>'text', 'encrypt'=>'encrypt' ) ;
|
||||
|
||||
$originalViewDefs = $this->getOriginalViewDefs();
|
||||
|
||||
foreach ( $this->_viewdefs as $key => $def )
|
||||
{
|
||||
//If the field is on the layout, but studio disabled, put it back on the layout at the front
|
||||
if (isset ($def['studio']) && (
|
||||
(is_array($def['studio']) && isset($def['studio']['listview']) &&
|
||||
($def['studio']['listview'] === false || strtolower($def['studio']['listview']) == 'false'
|
||||
|| strtolower($def['studio']['listview']) == 'required')
|
||||
)
|
||||
|| (!is_array($def['studio']) &&
|
||||
($def [ 'studio' ] === false || strtolower($def['studio']) == 'false' || strtolower($def['studio']) == 'required'))
|
||||
))
|
||||
{
|
||||
$newViewdefs [ $key ] = $def ;
|
||||
}
|
||||
}
|
||||
// only take items from group_0 for searchviews (basic_search or advanced_search) and subpanels (which both are missing the Available column) - take group_0, _1 and _2 for all other list views
|
||||
$lastGroup = (isset ( $this->columns [ 'LBL_AVAILABLE' ] )) ? 2 : 1 ;
|
||||
|
||||
for ( $i = 0 ; isset ( $_POST [ 'group_' . $i ] ) && $i < $lastGroup ; $i ++ )
|
||||
{
|
||||
foreach ( $_POST [ 'group_' . $i ] as $fieldname )
|
||||
{
|
||||
$fieldname = strtolower ( $fieldname ) ;
|
||||
//Check if the field was previously on the layout
|
||||
if (isset ($this->_viewdefs[$fieldname])) {
|
||||
$newViewdefs [ $fieldname ] = $this->_viewdefs[$fieldname];
|
||||
// print_r($this->_viewdefs[ $fieldname ]);
|
||||
}
|
||||
//Next check if the original view def contained it
|
||||
else if (isset($originalViewDefs[ $fieldname ]))
|
||||
{
|
||||
$newViewdefs [ $fieldname ] = $originalViewDefs[ $fieldname ];
|
||||
}
|
||||
//create a definition from the fielddefs
|
||||
else
|
||||
{
|
||||
// if we don't have a valid fieldname then just ignore it and move on...
|
||||
if ( ! isset ( $this->_fielddefs [ $fieldname ] ) )
|
||||
continue ;
|
||||
|
||||
$newViewdefs [ $fieldname ] = $this->_trimFieldDefs($this->_fielddefs [ $fieldname ]) ;
|
||||
// sorting fields of certain types will cause a database engine problems
|
||||
if ( isset($this->_fielddefs[$fieldname]['type']) &&
|
||||
isset ( $rejectTypes [ $this->_fielddefs [ $fieldname ] [ 'type' ] ] ))
|
||||
{
|
||||
$newViewdefs [ $fieldname ] [ 'sortable' ] = false ;
|
||||
}
|
||||
|
||||
// Bug 23728 - Make adding a currency type field default to setting the 'currency_format' to true
|
||||
if (isset ( $this->_fielddefs [ $fieldname ] [ 'type' ]) && $this->_fielddefs [ $fieldname ] [ 'type' ] == 'currency')
|
||||
{
|
||||
$newViewdefs [ $fieldname ] [ 'currency_format' ] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isset ( $_REQUEST [ strtolower ( $fieldname ) . 'width' ] ))
|
||||
{
|
||||
$width = substr ( $_REQUEST [ $fieldname . 'width' ], 6, 3 ) ;
|
||||
if (strpos ( $width, "%" ) != false)
|
||||
{
|
||||
$width = substr ( $width, 0, 2 ) ;
|
||||
}
|
||||
if (!($width < 101 && $width > 0))
|
||||
{
|
||||
$width = 10;
|
||||
}
|
||||
$newViewdefs [ $fieldname ] [ 'width' ] = $width."%" ;
|
||||
} else if (isset ( $this->_viewdefs [ $fieldname ] [ 'width' ] ))
|
||||
{
|
||||
$newViewdefs [ $fieldname ] [ 'width' ] = $this->_viewdefs [ $fieldname ] [ 'width' ] ;
|
||||
}
|
||||
else {
|
||||
$newViewdefs [ $fieldname ] [ 'width' ] = "10%";
|
||||
}
|
||||
|
||||
$newViewdefs [ $fieldname ] [ 'default' ] = ($i == 0) ;
|
||||
}
|
||||
}
|
||||
$this->_viewdefs = $newViewdefs ;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove all instances of a field from the layout
|
||||
* @param string $fieldName Name of the field to remove
|
||||
* @return boolean True if the field was removed; false otherwise
|
||||
*/
|
||||
function removeField ($fieldName)
|
||||
{
|
||||
if (isset ( $this->_viewdefs [ $fieldName ] ))
|
||||
{
|
||||
unset( $this->_viewdefs [ $fieldName ] ) ;
|
||||
return true ;
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
|
||||
function getOriginalViewDefs() {
|
||||
$defs = $this->implementation->getOriginalViewdefs ();
|
||||
$out = array();
|
||||
foreach ($defs as $field => $def)
|
||||
{
|
||||
$out[strtolower($field)] = $def;
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
static function _trimFieldDefs ( $def )
|
||||
{
|
||||
if ( isset ( $def [ 'vname' ] ) )
|
||||
$def [ 'label' ] = $def [ 'vname' ] ;
|
||||
return array_intersect_key ( $def , array ( 'type' => true, 'studio' => true , 'label' => true , 'width' => true , 'sortable' => true , 'related_fields' => true , 'default' => true , 'link' => true , 'align' => true , 'orderBy' => true ,'hideLabel' => true, 'customLable' => true , 'currency_format' => true ) ) ;
|
||||
}
|
||||
|
||||
}
|
||||
45
modules/ModuleBuilder/parsers/views/MetaDataImplementationInterface.php
Executable file
45
modules/ModuleBuilder/parsers/views/MetaDataImplementationInterface.php
Executable file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
|
||||
/*********************************************************************************
|
||||
* SugarCRM is a customer relationship management program developed by
|
||||
* SugarCRM, Inc. Copyright (C) 2004-2010 SugarCRM Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License version 3 as published by the
|
||||
* Free Software Foundation with the addition of the following permission added
|
||||
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
|
||||
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
|
||||
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License along with
|
||||
* this program; if not, see http://www.gnu.org/licenses or write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA.
|
||||
*
|
||||
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
|
||||
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "Powered by
|
||||
* SugarCRM" logo. If the display of the logo is not reasonably feasible for
|
||||
* technical reasons, the Appropriate Legal Notices must display the words
|
||||
* "Powered by SugarCRM".
|
||||
********************************************************************************/
|
||||
|
||||
interface MetaDataImplementationInterface
|
||||
{
|
||||
public function getViewdefs () ;
|
||||
public function getFielddefs () ;
|
||||
public function getLanguage () ;
|
||||
public function deploy ($defs) ;
|
||||
public function getHistory () ;
|
||||
}
|
||||
50
modules/ModuleBuilder/parsers/views/MetaDataParserInterface.php
Executable file
50
modules/ModuleBuilder/parsers/views/MetaDataParserInterface.php
Executable file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
|
||||
/*********************************************************************************
|
||||
* SugarCRM is a customer relationship management program developed by
|
||||
* SugarCRM, Inc. Copyright (C) 2004-2010 SugarCRM Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License version 3 as published by the
|
||||
* Free Software Foundation with the addition of the following permission added
|
||||
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
|
||||
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
|
||||
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License along with
|
||||
* this program; if not, see http://www.gnu.org/licenses or write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA.
|
||||
*
|
||||
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
|
||||
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "Powered by
|
||||
* SugarCRM" logo. If the display of the logo is not reasonably feasible for
|
||||
* technical reasons, the Appropriate Legal Notices must display the words
|
||||
* "Powered by SugarCRM".
|
||||
********************************************************************************/
|
||||
|
||||
interface MetaDataParserInterface
|
||||
{
|
||||
|
||||
public function handleSave () ;
|
||||
|
||||
public function getLayout () ;
|
||||
|
||||
public function getLanguage () ;
|
||||
|
||||
public function getHistory () ;
|
||||
|
||||
}
|
||||
?>
|
||||
233
modules/ModuleBuilder/parsers/views/PopupMetaDataParser.php
Executable file
233
modules/ModuleBuilder/parsers/views/PopupMetaDataParser.php
Executable file
@@ -0,0 +1,233 @@
|
||||
<?php
|
||||
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
|
||||
/*********************************************************************************
|
||||
* SugarCRM is a customer relationship management program developed by
|
||||
* SugarCRM, Inc. Copyright (C) 2004-2010 SugarCRM Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License version 3 as published by the
|
||||
* Free Software Foundation with the addition of the following permission added
|
||||
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
|
||||
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
|
||||
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License along with
|
||||
* this program; if not, see http://www.gnu.org/licenses or write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA.
|
||||
*
|
||||
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
|
||||
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "Powered by
|
||||
* SugarCRM" logo. If the display of the logo is not reasonably feasible for
|
||||
* technical reasons, the Appropriate Legal Notices must display the words
|
||||
* "Powered by SugarCRM".
|
||||
********************************************************************************/
|
||||
|
||||
require_once ('modules/ModuleBuilder/parsers/views/ListLayoutMetaDataParser.php') ;
|
||||
require_once ('modules/ModuleBuilder/parsers/views/SearchViewMetaDataParser.php') ;
|
||||
require_once 'modules/ModuleBuilder/parsers/constants.php' ;
|
||||
|
||||
class PopupMetaDataParser extends ListLayoutMetaDataParser
|
||||
{
|
||||
|
||||
// Columns is used by the view to construct the listview - each column is built by calling the named function
|
||||
public $columns = array ( 'LBL_DEFAULT' => 'getDefaultFields' , 'LBL_AVAILABLE' => 'getAdditionalFields' , 'LBL_HIDDEN' => 'getAvailableFields' ) ;
|
||||
|
||||
public static $reserveProperties = array('moduleMain', 'varName' , 'orderBy', 'whereClauses', 'searchInputs', 'create');
|
||||
|
||||
public static $defsMap = array(MB_POPUPSEARCH => 'searchdefs' , MB_POPUPLIST => 'listviewdefs');
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
* Must set:
|
||||
* $this->columns Array of 'Column LBL'=>function_to_retrieve_fields_for_this_column() - expected by the view
|
||||
*
|
||||
* @param string moduleName The name of the module to which this listview belongs
|
||||
* @param string packageName If not empty, the name of the package to which this listview belongs
|
||||
*/
|
||||
function __construct ($view, $moduleName , $packageName = '')
|
||||
{
|
||||
$this->search = ($view == MB_POPUPSEARCH) ? true : false;
|
||||
$this->_moduleName = $moduleName;
|
||||
$this->_packageName = $packageName;
|
||||
$this->_view = $view ;
|
||||
$this->columns = array ( 'LBL_DEFAULT' => 'getDefaultFields' , 'LBL_HIDDEN' => 'getAvailableFields' ) ;
|
||||
|
||||
if ($this->search)
|
||||
{
|
||||
$this->columns = array ( 'LBL_DEFAULT' => 'getSearchFields' , 'LBL_HIDDEN' => 'getAvailableFields' ) ;
|
||||
parent::__construct ( MB_POPUPSEARCH, $moduleName, $packageName ) ;
|
||||
} else
|
||||
{
|
||||
parent::__construct ( MB_POPUPLIST, $moduleName, $packageName ) ;
|
||||
}
|
||||
|
||||
$this->_viewdefs = $this->mergeFieldDefinitions($this->_viewdefs, $this->_fielddefs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dashlets contain both a searchview and list view definition, therefore we need to merge only the relevant info
|
||||
*/
|
||||
function mergeFieldDefinitions ( $viewdefs, $fielddefs ) {
|
||||
$viewdefs = $this->_viewdefs = array_change_key_case($viewdefs );
|
||||
$viewdefs = $this->_viewdefs = $this->convertSearchToListDefs($viewdefs);
|
||||
return $viewdefs;
|
||||
}
|
||||
|
||||
function convertSearchToListDefs($defs) {
|
||||
$temp = array();
|
||||
foreach($defs as $key=>$value) {
|
||||
if(!is_array($value)){
|
||||
$temp[$value] = array('name'=>$value);
|
||||
}else{
|
||||
$temp[$key] = $value;
|
||||
if(isset($value['name']) && $value['name'] != $key){
|
||||
$temp[$value['name']] = $value;
|
||||
unset($temp[$key] );
|
||||
}else if( !isset($value['name']) ){
|
||||
$temp[$key]['name'] = $key;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $temp;
|
||||
}
|
||||
|
||||
function getOriginalViewDefs(){
|
||||
$defs = parent::getOriginalViewDefs();
|
||||
return $this->convertSearchToListDefs($defs);
|
||||
}
|
||||
|
||||
public function getSearchFields()
|
||||
{
|
||||
$searchFields = array ( ) ;
|
||||
foreach ( $this->_viewdefs as $key => $def )
|
||||
{
|
||||
if (isset($this->_fielddefs [ $key ] )) {
|
||||
$searchFields [ $key ] = self::_trimFieldDefs ( $this->_fielddefs [ $key ] ) ;
|
||||
if (!empty($def['label']))
|
||||
$searchFields [ $key ]['label'] = $def['label'];
|
||||
}
|
||||
else {
|
||||
$searchFields [ $key ] = $def;
|
||||
}
|
||||
}
|
||||
|
||||
return $searchFields ;
|
||||
}
|
||||
|
||||
function handleSave ($populate = true)
|
||||
{
|
||||
if (empty ( $this->_packageName ))
|
||||
{
|
||||
foreach(array(MB_CUSTOMMETADATALOCATION , MB_BASEMETADATALOCATION) as $value){
|
||||
$file = $this->implementation->getFileName(MB_POPUPLIST, $this->_moduleName, $value);
|
||||
if(file_exists($file)){
|
||||
break;
|
||||
}
|
||||
}
|
||||
$writeFile = $this->implementation->getFileName(MB_POPUPLIST, $this->_moduleName);
|
||||
if(!file_exists($writeFile)){
|
||||
mkdir_recursive ( dirname ( $writeFile ) ) ;
|
||||
}
|
||||
}
|
||||
else{
|
||||
$writeFile = $file = $this->implementation->getFileName(MB_POPUPLIST, $this->_moduleName, $this->_packageName);
|
||||
}
|
||||
$this->implementation->_history->append ( $file ) ;
|
||||
if ($populate)
|
||||
$this->_populateFromRequest() ;
|
||||
$out = "<?php\n" ;
|
||||
|
||||
//Load current module languages
|
||||
global $mod_strings , $current_language;
|
||||
$oldModStrings = $mod_strings;
|
||||
$GLOBALS['mod_strings'] = return_module_language($current_language , $this->_moduleName);
|
||||
require($file);
|
||||
if (!isset($popupMeta)) {
|
||||
sugar_die ("unable to load Module Popup Definition");
|
||||
}
|
||||
|
||||
if ($this->_view == MB_POPUPSEARCH)
|
||||
{
|
||||
foreach($this->_viewdefs as $k => $v){
|
||||
if(isset($this->_viewdefs[$k]) && isset($this->_viewdefs[$k]['default'])){
|
||||
unset($this->_viewdefs[$k]['default']);
|
||||
}
|
||||
}
|
||||
$this->_viewdefs = $this->convertSearchToListDefs($this->_viewdefs);
|
||||
$popupMeta['searchdefs'] = $this->_viewdefs;
|
||||
$this->addNewSearchDef($this->_viewdefs , $popupMeta);
|
||||
} else
|
||||
{
|
||||
$popupMeta['listviewdefs'] = array_change_key_case($this->_viewdefs , CASE_UPPER );
|
||||
}
|
||||
$allProperties = array_merge(self::$reserveProperties , array('searchdefs', 'listviewdefs'));
|
||||
|
||||
$out .= "\$popupMeta = array (\n";
|
||||
foreach( $allProperties as $p){
|
||||
if(isset($popupMeta[$p])){
|
||||
$out .= " '$p' => ". var_export_helper ($popupMeta[$p]) . ",\n";
|
||||
}
|
||||
}
|
||||
$out .= ");\n";
|
||||
file_put_contents($writeFile, $out);
|
||||
|
||||
//return back mod strings
|
||||
$GLOBALS['mod_strings'] = $oldModStrings;
|
||||
}
|
||||
|
||||
public function addNewSearchDef($searchDefs, &$popupMeta){
|
||||
if(!empty($searchDefs)){
|
||||
$this->__diffAndUpdate( $searchDefs , $popupMeta['whereClauses'] , true);
|
||||
$this->__diffAndUpdate( $searchDefs , $popupMeta['searchInputs'] );
|
||||
}
|
||||
}
|
||||
|
||||
private function __diffAndUpdate($newDefs , &$targetDefs , $forWhere = false){
|
||||
if(!is_array($targetDefs)){
|
||||
$targetDefs = array();
|
||||
}
|
||||
foreach($newDefs as $key =>$def){
|
||||
if(!isset($targetDefs[$key]) && $forWhere){
|
||||
$targetDefs[$key] = $this->__getTargetModuleName($def).'.'.$key;
|
||||
}else if( !in_array($key , $targetDefs ) && !$forWhere){
|
||||
array_push($targetDefs , $key);
|
||||
}
|
||||
}
|
||||
|
||||
if($forWhere){
|
||||
foreach(array_diff( array_keys($targetDefs) , array_keys($newDefs) ) as $key ){
|
||||
unset($targetDefs[$key]);
|
||||
}
|
||||
}else{
|
||||
foreach($targetDefs as $key =>$value){
|
||||
if(!isset($newDefs[$value]))
|
||||
unset($targetDefs[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private function __getTargetModuleName($def){
|
||||
$dir = strtolower($this->implementation->getModuleDir());
|
||||
if(isset($this->_fielddefs[$def['name']]) && isset($this->_fielddefs[$def['name']]['source']) && $this->_fielddefs[$def['name']]['source'] == 'custom_fields'){
|
||||
return $dir.'_cstm';
|
||||
}
|
||||
|
||||
return $dir;
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
||||
200
modules/ModuleBuilder/parsers/views/SearchViewMetaDataParser.php
Executable file
200
modules/ModuleBuilder/parsers/views/SearchViewMetaDataParser.php
Executable file
@@ -0,0 +1,200 @@
|
||||
<?php
|
||||
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
|
||||
/*********************************************************************************
|
||||
* SugarCRM is a customer relationship management program developed by
|
||||
* SugarCRM, Inc. Copyright (C) 2004-2010 SugarCRM Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License version 3 as published by the
|
||||
* Free Software Foundation with the addition of the following permission added
|
||||
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
|
||||
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
|
||||
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License along with
|
||||
* this program; if not, see http://www.gnu.org/licenses or write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA.
|
||||
*
|
||||
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
|
||||
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "Powered by
|
||||
* SugarCRM" logo. If the display of the logo is not reasonably feasible for
|
||||
* technical reasons, the Appropriate Legal Notices must display the words
|
||||
* "Powered by SugarCRM".
|
||||
********************************************************************************/
|
||||
|
||||
|
||||
require_once ('modules/ModuleBuilder/parsers/views/ListLayoutMetaDataParser.php') ;
|
||||
require_once 'modules/ModuleBuilder/parsers/constants.php' ;
|
||||
|
||||
class SearchViewMetaDataParser extends ListLayoutMetaDataParser
|
||||
{
|
||||
static $variableMap = array (
|
||||
MB_BASICSEARCH => 'basic_search' ,
|
||||
MB_ADVANCEDSEARCH => 'advanced_search' ,
|
||||
) ;
|
||||
// Columns is used by the view to construct the listview - each column is built by calling the named function
|
||||
public $columns = array ( 'LBL_DEFAULT' => 'getDefaultFields' , 'LBL_HIDDEN' => 'getAvailableFields' ) ;
|
||||
protected $allowParent = true;
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
* Must set:
|
||||
* $this->columns Array of 'Column LBL'=>function_to_retrieve_fields_for_this_column() - expected by the view
|
||||
* @param string searchLayout The type of search layout, e.g., MB_BASICSEARCH or MB_ADVANCEDSEARCH
|
||||
* @param string moduleName The name of the module to which this listview belongs
|
||||
* @param string packageName If not empty, the name of the package to which this listview belongs
|
||||
*/
|
||||
function __construct ($searchLayout, $moduleName , $packageName = '')
|
||||
{
|
||||
$GLOBALS [ 'log' ]->debug ( get_class ( $this ) . ": __construct( $searchLayout , $moduleName , $packageName )" ) ;
|
||||
|
||||
// BEGIN ASSERTIONS
|
||||
if (! isset ( self::$variableMap [ $searchLayout ] ) )
|
||||
{
|
||||
sugar_die ( get_class ( $this ) . ": View $searchLayout is not supported" ) ;
|
||||
}
|
||||
// END ASSERTIONS
|
||||
|
||||
$this->_searchLayout = $searchLayout ;
|
||||
|
||||
// unsophisticated error handling for now...
|
||||
try
|
||||
{
|
||||
if (empty ( $packageName ))
|
||||
{
|
||||
require_once 'modules/ModuleBuilder/parsers/views/DeployedMetaDataImplementation.php' ;
|
||||
$this->implementation = new DeployedMetaDataImplementation ( $searchLayout, $moduleName ) ;
|
||||
} else
|
||||
{
|
||||
require_once 'modules/ModuleBuilder/parsers/views/UndeployedMetaDataImplementation.php' ;
|
||||
$this->implementation = new UndeployedMetaDataImplementation ( $searchLayout, $moduleName, $packageName ) ;
|
||||
}
|
||||
} catch (Exception $e)
|
||||
{
|
||||
throw $e ;
|
||||
}
|
||||
|
||||
$this->_saved = array_change_key_case ( $this->implementation->getViewdefs () ) ; // force to lower case so don't have problems with case mismatches later
|
||||
if(isset($this->_saved['templatemeta'])) {
|
||||
$this->_saved['templateMeta'] = $this->_saved['templatemeta'];
|
||||
unset($this->_saved['templatemeta']);
|
||||
}
|
||||
|
||||
if ( ! isset ( $this->_saved [ 'layout' ] [ self::$variableMap [ $this->_searchLayout ] ] ) )
|
||||
{
|
||||
// attempt to fallback on a basic_search layout...
|
||||
|
||||
if ( ! isset ( $this->_saved [ 'layout' ] [ self::$variableMap [ MB_BASICSEARCH ] ] ) )
|
||||
throw new Exception ( get_class ( $this ) . ": {$this->_searchLayout} does not exist for module $moduleName" ) ;
|
||||
|
||||
$this->_saved [ 'layout'] [ MB_ADVANCEDSEARCH ] = $this->_saved [ 'layout' ] [ MB_BASICSEARCH ] ;
|
||||
}
|
||||
|
||||
$this->view = $searchLayout;
|
||||
// convert the search view layout (which has its own unique layout form) to the standard listview layout so that the parser methods and views can be reused
|
||||
$this->_viewdefs = $this->convertSearchViewToListView ( $this->_saved [ 'layout' ] [ self::$variableMap [ $this->_searchLayout ] ] ) ;
|
||||
$this->_fielddefs = $this->implementation->getFielddefs () ;
|
||||
$this->_standardizeFieldLabels( $this->_fielddefs );
|
||||
|
||||
}
|
||||
|
||||
public function isValidField($key, $def)
|
||||
{
|
||||
|
||||
if (!parent::isValidField($key, $def))
|
||||
return false;
|
||||
|
||||
if (isset($def [ 'studio' ]) && is_array($def [ 'studio' ]) && isset($def [ 'studio' ]['searchview']))
|
||||
{
|
||||
return $def [ 'studio' ]['searchview'] !== false && $def [ 'studio' ]['searchview'] != 'false';
|
||||
}
|
||||
|
||||
//Special case to prevent multiple copies of assigned user on the search view
|
||||
if (empty ($def[ 'studio' ] ) && $key == "assigned_user_name" )
|
||||
{
|
||||
$origDefs = $this->getOriginalViewDefs();
|
||||
if (isset($origDefs['assigned_user_id']))
|
||||
return false;
|
||||
}
|
||||
|
||||
//Remove image fields (unless studio was set)
|
||||
if (!empty($def [ 'studio' ]) && isset($def['type']) && $def['type'] == "image")
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Save the modified searchLayout
|
||||
* Have to preserve the original layout format, which is array('metadata'=>array,'layouts'=>array('basic'=>array,'advanced'=>array))
|
||||
*/
|
||||
function handleSave ($populate = true)
|
||||
{
|
||||
if ($populate)
|
||||
$this->_populateFromRequest() ;
|
||||
|
||||
|
||||
$this->_saved [ 'layout' ] [ self::$variableMap [ $this->_searchLayout ] ] = $this->convertSearchViewToListView($this->_viewdefs);;
|
||||
$this->implementation->deploy ( $this->_saved ) ;
|
||||
}
|
||||
|
||||
private function convertSearchViewToListView ($viewdefs)
|
||||
{
|
||||
$temp = array ( ) ;
|
||||
foreach ( $viewdefs as $key => $value )
|
||||
{
|
||||
if (! is_array ( $value ))
|
||||
{
|
||||
$key = $value ;
|
||||
$def = array ( ) ;
|
||||
$def[ 'name' ] = $key;
|
||||
$value = $def ;
|
||||
}
|
||||
|
||||
if (!isset ( $value [ 'name' ] ))
|
||||
{
|
||||
$value [ 'name' ] = $key;
|
||||
}
|
||||
else
|
||||
{
|
||||
$key = $value [ 'name' ] ; // override key with name, needed when the entry lacks a key
|
||||
}
|
||||
// now add in the standard listview default=>true
|
||||
$value [ 'default' ] = true ;
|
||||
$temp [ strtolower ( $key ) ] = $value ;
|
||||
}
|
||||
return $temp ;
|
||||
}
|
||||
|
||||
function getOriginalViewDefs() {
|
||||
$defs = $this->implementation->getOriginalViewdefs ();
|
||||
$out = array();
|
||||
if (!empty($defs) && !empty($defs['layout']) && !empty($defs['layout'][$this->_searchLayout]))
|
||||
{
|
||||
$defs = $defs['layout'][$this->_searchLayout];
|
||||
foreach ($defs as $def)
|
||||
{
|
||||
if (is_array($def) && isset($def['name']))
|
||||
{
|
||||
$out[strtolower($def['name'])] = $def;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
}
|
||||
?>
|
||||
161
modules/ModuleBuilder/parsers/views/SubpanelMetaDataParser.php
Executable file
161
modules/ModuleBuilder/parsers/views/SubpanelMetaDataParser.php
Executable file
@@ -0,0 +1,161 @@
|
||||
<?php
|
||||
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
|
||||
/*********************************************************************************
|
||||
* SugarCRM is a customer relationship management program developed by
|
||||
* SugarCRM, Inc. Copyright (C) 2004-2010 SugarCRM Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License version 3 as published by the
|
||||
* Free Software Foundation with the addition of the following permission added
|
||||
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
|
||||
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
|
||||
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License along with
|
||||
* this program; if not, see http://www.gnu.org/licenses or write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA.
|
||||
*
|
||||
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
|
||||
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "Powered by
|
||||
* SugarCRM" logo. If the display of the logo is not reasonably feasible for
|
||||
* technical reasons, the Appropriate Legal Notices must display the words
|
||||
* "Powered by SugarCRM".
|
||||
********************************************************************************/
|
||||
|
||||
|
||||
require_once ('modules/ModuleBuilder/parsers/views/ListLayoutMetaDataParser.php') ;
|
||||
require_once 'modules/ModuleBuilder/parsers/constants.php' ;
|
||||
|
||||
class SubpanelMetaDataParser extends ListLayoutMetaDataParser
|
||||
{
|
||||
|
||||
// Columns is used by the view to construct the listview - each column is built by calling the named function
|
||||
public $columns = array ( 'LBL_DEFAULT' => 'getDefaultFields' , 'LBL_HIDDEN' => 'getAvailableFields' ) ;
|
||||
protected $labelIdentifier = 'vname' ; // labels in the subpanel defs are tagged 'vname' =>
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
* Must set:
|
||||
* $this->columns Array of 'Column LBL'=>function_to_retrieve_fields_for_this_column() - expected by the view
|
||||
*
|
||||
* @param string subpanelName The name of this subpanel
|
||||
* @param string moduleName The name of the module to which this subpanel belongs
|
||||
* @param string packageName If not empty, the name of the package to which this subpanel belongs
|
||||
*/
|
||||
function __construct ($subpanelName , $moduleName , $packageName = '')
|
||||
{
|
||||
$GLOBALS [ 'log' ]->debug ( get_class ( $this ) . ": __construct()" ) ;
|
||||
|
||||
// TODO: check the implementations
|
||||
if (empty ( $packageName ))
|
||||
{
|
||||
require_once 'modules/ModuleBuilder/parsers/views/DeployedSubpanelImplementation.php' ;
|
||||
$this->implementation = new DeployedSubpanelImplementation ( $subpanelName, $moduleName ) ;
|
||||
//$this->originalViewDef = $this->implementation->getOriginalDefs ();
|
||||
} else
|
||||
{
|
||||
require_once 'modules/ModuleBuilder/parsers/views/UndeployedSubpanelImplementation.php' ;
|
||||
$this->implementation = new UndeployedSubpanelImplementation ( $subpanelName, $moduleName, $packageName ) ;
|
||||
}
|
||||
|
||||
$this->_viewdefs = array_change_key_case ( $this->implementation->getViewdefs () ) ; // force to lower case so don't have problems with case mismatches later
|
||||
$this->_fielddefs = $this->implementation->getFielddefs ();
|
||||
$this->_standardizeFieldLabels( $this->_fielddefs );
|
||||
$GLOBALS['log']->debug ( get_class($this)."->__construct(): viewdefs = ".print_r($this->_viewdefs,true));
|
||||
$GLOBALS['log']->debug ( get_class($this)."->__construct(): viewdefs = ".print_r($this->_viewdefs,true));
|
||||
$this->_invisibleFields = $this->findInvisibleFields( $this->_viewdefs ) ;
|
||||
|
||||
$GLOBALS['log']->debug ( get_class($this)."->__construct(): invisibleFields = ".print_r($this->_invisibleFields,true));
|
||||
}
|
||||
|
||||
/*
|
||||
* Save the layout
|
||||
*/
|
||||
function handleSave ($populate = true)
|
||||
{
|
||||
if ($populate)
|
||||
{
|
||||
$this->_populateFromRequest() ;
|
||||
if (isset ($_REQUEST['subpanel_title']) && isset($_REQUEST['subpanel_title_key'])) {
|
||||
$selected_lang = (!empty($_REQUEST['selected_lang'])? $_REQUEST['selected_lang']:$_SESSION['authenticated_user_language']);
|
||||
if(empty($selected_lang)){
|
||||
$selected_lang = $GLOBALS['sugar_config']['default_language'];
|
||||
}
|
||||
require_once 'modules/ModuleBuilder/parsers/parser.label.php' ;
|
||||
$labelParser = new ParserLabel ( $_REQUEST['view_module'] , isset ( $_REQUEST [ 'view_package' ] ) ? $_REQUEST [ 'view_package' ] : null ) ;
|
||||
$labelParser->addLabels($selected_lang, array($_REQUEST['subpanel_title_key'] => $_REQUEST['subpanel_title']), $_REQUEST['view_module']);
|
||||
}
|
||||
}
|
||||
|
||||
$this->implementation->deploy ( $this->restoreInvisibleFields ( $this->_invisibleFields , $this->_viewdefs ) ) ; // unlike our parent, do not force the field names back to upper case
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of the default fields for a subpanel
|
||||
* TODO: have this return just a list of fields, without definitions
|
||||
* @return array List of default fields as an array, where key = value = <field name>
|
||||
*/
|
||||
function getDefaultFields ()
|
||||
{
|
||||
$defaultFields = array ( ) ;
|
||||
foreach ( $this->_viewdefs as $key => $def )
|
||||
{
|
||||
if (empty ( $def [ 'usage' ] ) || strcmp ( $def [ 'usage' ], 'query_only' ) == 1)
|
||||
{
|
||||
$defaultFields [ strtolower ( $key ) ] = $this->_viewdefs [ $key ] ;
|
||||
}
|
||||
}
|
||||
|
||||
return $defaultFields ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the query_only fields in the viewdefs
|
||||
* Query_only fields are used by the MVC to generate the subpanel but are not editable - they must be maintained in the layout
|
||||
* @param viewdefs The viewdefs to be searched for invisible fields
|
||||
* @return Array of invisible fields, ready to be provided to $this->restoreInvisibleFields
|
||||
*/
|
||||
function findInvisibleFields( $viewdefs )
|
||||
{
|
||||
$invisibleFields = array () ;
|
||||
foreach ( $viewdefs as $name => $def )
|
||||
if ( isset($def [ 'usage' ] ) && ($def [ 'usage'] == 'query_only') )
|
||||
$invisibleFields [ $name ] = $def ;
|
||||
return $invisibleFields ;
|
||||
}
|
||||
|
||||
function restoreInvisibleFields ( $invisibleFields , $viewdefs )
|
||||
{
|
||||
foreach ( $invisibleFields as $name => $def )
|
||||
{
|
||||
$viewdefs [ $name ] = $def ;
|
||||
}
|
||||
return $viewdefs ;
|
||||
}
|
||||
|
||||
static function _trimFieldDefs ( $def )
|
||||
{
|
||||
$listDef = parent::_trimFieldDefs($def);
|
||||
if (isset($listDef ['label']))
|
||||
{
|
||||
$listDef ['vname'] = $listDef ['label'];
|
||||
unset($listDef ['label']);
|
||||
}
|
||||
return $listDef;
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
||||
206
modules/ModuleBuilder/parsers/views/UndeployedMetaDataImplementation.php
Executable file
206
modules/ModuleBuilder/parsers/views/UndeployedMetaDataImplementation.php
Executable file
@@ -0,0 +1,206 @@
|
||||
<?php
|
||||
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
|
||||
/*********************************************************************************
|
||||
* SugarCRM is a customer relationship management program developed by
|
||||
* SugarCRM, Inc. Copyright (C) 2004-2010 SugarCRM Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License version 3 as published by the
|
||||
* Free Software Foundation with the addition of the following permission added
|
||||
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
|
||||
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
|
||||
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License along with
|
||||
* this program; if not, see http://www.gnu.org/licenses or write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA.
|
||||
*
|
||||
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
|
||||
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "Powered by
|
||||
* SugarCRM" logo. If the display of the logo is not reasonably feasible for
|
||||
* technical reasons, the Appropriate Legal Notices must display the words
|
||||
* "Powered by SugarCRM".
|
||||
********************************************************************************/
|
||||
|
||||
require_once 'modules/ModuleBuilder/MB/ModuleBuilder.php' ;
|
||||
require_once 'modules/ModuleBuilder/parsers/views/AbstractMetaDataImplementation.php' ;
|
||||
require_once 'modules/ModuleBuilder/parsers/views/MetaDataImplementationInterface.php' ;
|
||||
require_once 'modules/ModuleBuilder/parsers/views/ListLayoutMetaDataParser.php' ;
|
||||
require_once 'modules/ModuleBuilder/parsers/views/GridLayoutMetaDataParser.php' ;
|
||||
require_once 'modules/ModuleBuilder/parsers/constants.php' ;
|
||||
|
||||
class UndeployedMetaDataImplementation extends AbstractMetaDataImplementation implements MetaDataImplementationInterface
|
||||
{
|
||||
|
||||
private $_packageName ;
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
* @param string $view
|
||||
* @param string $moduleName
|
||||
* @throws Exception Thrown if the provided view doesn't exist for this module
|
||||
*/
|
||||
|
||||
function __construct ($view , $moduleName , $packageName)
|
||||
{
|
||||
|
||||
// BEGIN ASSERTIONS
|
||||
if (! isset ( $this->_fileVariables [ $view ] ))
|
||||
{
|
||||
sugar_die ( get_class ( $this ) . ": View $view is not supported" ) ;
|
||||
}
|
||||
// END ASSERTIONS
|
||||
|
||||
$this->_view = strtolower ( $view ) ;
|
||||
$this->_moduleName = $moduleName ;
|
||||
$this->_packageName = $packageName ;
|
||||
|
||||
//get the bean from ModuleBuilder
|
||||
$mb = new ModuleBuilder ( ) ;
|
||||
$this->module = $module = & $mb->getPackageModule ( $packageName, $moduleName ) ;
|
||||
$pak = $mb->getPackage($packageName);
|
||||
$module->mbvardefs->updateVardefs () ;
|
||||
|
||||
// Set the list of fields associated with this module
|
||||
$fielddefs = array_change_key_case ( $module->mbvardefs->vardefs [ 'fields' ] ) ;
|
||||
|
||||
// Set the global mod_strings directly as Sugar does not automatically load the language files for undeployed modules (how could it?)
|
||||
$GLOBALS [ 'mod_strings' ] = array_merge ( $GLOBALS [ 'mod_strings' ], $module->getModStrings () ) ;
|
||||
|
||||
//Load relationshhip based fields and labels
|
||||
$moduleRels = $pak->getRelationshipsForModule($moduleName);
|
||||
foreach($moduleRels as $rName => $rel ) {
|
||||
$varDefsSet = $rel->buildVardefs();
|
||||
if (!empty($varDefsSet[$module->key_name])) {
|
||||
foreach ($varDefsSet[$module->key_name] as $def) {
|
||||
$fielddefs[$def['name']] = $def;
|
||||
}
|
||||
}
|
||||
$labels = $rel->buildLabels();
|
||||
foreach ($labels as $def) {
|
||||
if ($def['module'] == $module->key_name) {
|
||||
$GLOBALS [ 'mod_strings' ][$def['system_label']] = $def['display_label'];
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$loaded = null ;
|
||||
foreach ( array ( MB_WORKINGMETADATALOCATION , MB_HISTORYMETADATALOCATION ) as $type )
|
||||
{
|
||||
$this->_sourceFilename = $this->getFileName ( $view, $moduleName, $packageName , $type ) ;
|
||||
if($view == MB_POPUPSEARCH || $view == MB_POPUPLIST){
|
||||
$layout = $this->_loadFromPopupFile ( $this->_sourceFilename , null, $view);
|
||||
}else{
|
||||
$layout = $this->_loadFromFile ( $this->_sourceFilename );
|
||||
}
|
||||
if ( null !== $layout )
|
||||
{
|
||||
// merge in the fielddefs from this layout
|
||||
$this->_mergeFielddefs ( $fielddefs , $layout ) ;
|
||||
$loaded = $layout ;
|
||||
}
|
||||
}
|
||||
|
||||
if ($loaded === null)
|
||||
{
|
||||
throw new Exception ( get_class ( $this ) . ": view definitions for View $this->_view and Module $this->_moduleName are missing" ) ;
|
||||
}
|
||||
|
||||
$this->_viewdefs = $loaded ;
|
||||
$sourceFilename = $this->getFileName ( $view, $moduleName, $packageName, MB_WORKINGMETADATALOCATION );
|
||||
if($view == MB_POPUPSEARCH || $view == MB_POPUPLIST){
|
||||
$layout = $this->_loadFromPopupFile ( $sourceFilename , null, $view);
|
||||
}else{
|
||||
$layout = $this->_loadFromFile ($sourceFilename) ;
|
||||
}
|
||||
$this->_originalViewdefs = $layout ;
|
||||
$this->_fielddefs = $fielddefs ;
|
||||
$this->_history = new History ( $this->getFileName ( $view, $moduleName, $packageName, MB_HISTORYMETADATALOCATION ) ) ;
|
||||
}
|
||||
|
||||
function getLanguage ()
|
||||
{
|
||||
return $this->_packageName . $this->_moduleName ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Deploy a layout
|
||||
* @param array defs Layout definition in the same format as received by the constructor
|
||||
*/
|
||||
function deploy ($defs)
|
||||
{
|
||||
//If we are pulling from the History Location, that means we did a restore, and we need to save the history for the previous file.
|
||||
if ($this->_sourceFilename == $this->getFileName ( $this->_view, $this->_moduleName, $this->_packageName, MB_HISTORYMETADATALOCATION )
|
||||
&& file_exists($this->getFileName ( $this->_view, $this->_moduleName, $this->_packageName, MB_WORKINGMETADATALOCATION ))) {
|
||||
$this->_history->append ( $this->getFileName ( $this->_view, $this->_moduleName, $this->_packageName, MB_WORKINGMETADATALOCATION )) ;
|
||||
} else {
|
||||
$this->_history->append ( $this->_sourceFilename ) ;
|
||||
}
|
||||
$filename = $this->getFileName ( $this->_view, $this->_moduleName, $this->_packageName, MB_WORKINGMETADATALOCATION ) ;
|
||||
$GLOBALS [ 'log' ]->debug ( get_class ( $this ) . "->deploy(): writing to " . $filename ) ;
|
||||
$this->_saveToFile ( $filename, $defs ) ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct a full pathname for the requested metadata
|
||||
* @param string view The view type, that is, EditView, DetailView etc
|
||||
* @param string modulename The name of the module that will use this layout
|
||||
* @param string type
|
||||
*/
|
||||
public static function getFileName ($view , $moduleName , $packageName , $type = MB_BASEMETADATALOCATION)
|
||||
{
|
||||
|
||||
$type = strtolower ( $type ) ;
|
||||
|
||||
// BEGIN ASSERTIONS
|
||||
if ($type != MB_BASEMETADATALOCATION && $type != MB_HISTORYMETADATALOCATION)
|
||||
{
|
||||
// just warn rather than die
|
||||
$GLOBALS [ 'log' ]->warning ( "UndeployedMetaDataImplementation->getFileName(): view type $type is not recognized" ) ;
|
||||
}
|
||||
// END ASSERTIONS
|
||||
|
||||
$filenames = array ( MB_DASHLETSEARCH => 'dashletviewdefs',
|
||||
MB_DASHLET => 'dashletviewdefs',
|
||||
MB_LISTVIEW => 'listviewdefs' ,
|
||||
MB_BASICSEARCH => 'searchdefs' ,
|
||||
MB_ADVANCEDSEARCH => 'searchdefs' ,
|
||||
MB_EDITVIEW => 'editviewdefs' ,
|
||||
MB_DETAILVIEW => 'detailviewdefs' ,
|
||||
MB_QUICKCREATE => 'quickcreatedefs',
|
||||
MB_POPUPSEARCH => 'popupdefs',
|
||||
MB_POPUPLIST => 'popupdefs',
|
||||
) ;
|
||||
|
||||
switch ( $type)
|
||||
{
|
||||
case MB_HISTORYMETADATALOCATION :
|
||||
return 'custom/history/modulebuilder/packages/' . $packageName . '/modules/' . $moduleName . '/metadata/' . $filenames [ $view ] . '.php' ;
|
||||
default :
|
||||
// get the module again, all so we can call this method statically without relying on the module stored in the class variables
|
||||
$mb = new ModuleBuilder ( ) ;
|
||||
$module = & $mb->getPackageModule ( $packageName, $moduleName ) ;
|
||||
return $module->getModuleDir () . '/metadata/' . $filenames [ $view ] . '.php' ;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function getModuleDir(){
|
||||
return $this->module->key_name;
|
||||
}
|
||||
}
|
||||
?>
|
||||
109
modules/ModuleBuilder/parsers/views/UndeployedSubpanelImplementation.php
Executable file
109
modules/ModuleBuilder/parsers/views/UndeployedSubpanelImplementation.php
Executable file
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
|
||||
/*********************************************************************************
|
||||
* SugarCRM is a customer relationship management program developed by
|
||||
* SugarCRM, Inc. Copyright (C) 2004-2010 SugarCRM Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License version 3 as published by the
|
||||
* Free Software Foundation with the addition of the following permission added
|
||||
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
|
||||
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
|
||||
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License along with
|
||||
* this program; if not, see http://www.gnu.org/licenses or write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA.
|
||||
*
|
||||
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
|
||||
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "Powered by
|
||||
* SugarCRM" logo. If the display of the logo is not reasonably feasible for
|
||||
* technical reasons, the Appropriate Legal Notices must display the words
|
||||
* "Powered by SugarCRM".
|
||||
********************************************************************************/
|
||||
/*
|
||||
* Changes to AbstractSubpanelImplementation for DeployedSubpanels
|
||||
* The main differences are in the load and save of the definitions
|
||||
* For subpanels we must make use of the SubPanelDefinitions class to do this; this also means that the history mechanism,
|
||||
* which tracks files, not objects, needs us to create an intermediate file representation of the definition that it can manage and restore
|
||||
*/
|
||||
|
||||
require_once 'modules/ModuleBuilder/parsers/views/MetaDataImplementationInterface.php' ;
|
||||
require_once 'modules/ModuleBuilder/parsers/views/AbstractMetaDataImplementation.php' ;
|
||||
require_once 'modules/ModuleBuilder/parsers/constants.php' ;
|
||||
|
||||
class UndeployedSubpanelImplementation extends AbstractMetaDataImplementation implements MetaDataImplementationInterface
|
||||
{
|
||||
|
||||
const HISTORYFILENAME = 'restored.php' ;
|
||||
const HISTORYVARIABLENAME = 'layout_defs' ;
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
* @param string subpanelName The name of this subpanel
|
||||
* @param string moduleName The name of the module to which this subpanel belongs
|
||||
* @param string packageName If not empty, the name of the package to which this subpanel belongs
|
||||
*/
|
||||
function __construct ($subpanelName , $moduleName , $packageName)
|
||||
{
|
||||
$this->_subpanelName = $subpanelName ;
|
||||
$this->_moduleName = $moduleName ;
|
||||
|
||||
// TODO: history
|
||||
$this->historyPathname = 'custom/history/modulebuilder/packages/' . $packageName . '/modules/' . $moduleName . '/metadata/' . self::HISTORYFILENAME ;
|
||||
$this->_history = new History ( $this->historyPathname ) ;
|
||||
|
||||
//get the bean from ModuleBuilder
|
||||
$mb = new ModuleBuilder ( ) ;
|
||||
$this->module = & $mb->getPackageModule ( $packageName, $moduleName ) ;
|
||||
$this->module->mbvardefs->updateVardefs () ;
|
||||
$this->_fielddefs = & $this->module->mbvardefs->vardefs [ 'fields' ] ;
|
||||
|
||||
$subpanel_layout = $this->module->getAvailibleSubpanelDef ( $this->_subpanelName ) ;
|
||||
$this->_viewdefs = & $subpanel_layout [ 'list_fields' ] ;
|
||||
$this->_mergeFielddefs($this->_fielddefs, $this->_viewdefs);
|
||||
|
||||
// Set the global mod_strings directly as Sugar does not automatically load the language files for undeployed modules (how could it?)
|
||||
$GLOBALS [ 'mod_strings' ] = array_merge ( $GLOBALS [ 'mod_strings' ], $this->module->getModStrings () ) ;
|
||||
}
|
||||
|
||||
function getLanguage ()
|
||||
{
|
||||
return "" ; // '' is the signal to translate() to use the global mod_strings
|
||||
}
|
||||
|
||||
/*
|
||||
* Save a subpanel
|
||||
* @param array defs Layout definition in the same format as received by the constructor
|
||||
* @param string type The location for the file - for example, MB_BASEMETADATALOCATION for a location in the OOB metadata directory
|
||||
*/
|
||||
function deploy ($defs)
|
||||
{
|
||||
$outputDefs = $this->module->getAvailibleSubpanelDef ( $this->_subpanelName ) ;
|
||||
// first sort out the historical record...
|
||||
// copy the definition to a temporary file then let the history object add it
|
||||
write_array_to_file ( self::HISTORYVARIABLENAME, $outputDefs, $this->historyPathname, 'w', '' ) ;
|
||||
$this->_history->append ( $this->historyPathname ) ;
|
||||
// no need to unlink the temporary file as being handled by in history->append()
|
||||
//unlink ( $this->historyPathname ) ;
|
||||
|
||||
$outputDefs [ 'list_fields' ] = $defs ;
|
||||
$this->_viewdefs = $defs ;
|
||||
$this->module->saveAvailibleSubpanelDef ( $this->_subpanelName, $outputDefs ) ;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user