N°931 new TagField iTop class generated for each AttributeTag field

SVN:trunk[6015]
This commit is contained in:
Pierre Goiffon
2018-08-23 15:06:17 +00:00
parent bdb62de81c
commit 961f5fd387
3 changed files with 214 additions and 49 deletions

View File

@@ -29,6 +29,7 @@ MetaModel::IncludeModule('core/action.class.inc.php');
MetaModel::IncludeModule('core/trigger.class.inc.php');
MetaModel::IncludeModule('core/bulkexport.class.inc.php');
MetaModel::IncludeModule('core/ownershiplock.class.inc.php');
MetaModel::IncludeModule('core/tagfield.class.inc.php');
MetaModel::IncludeModule('synchro/synchrodatasource.class.inc.php');
MetaModel::IncludeModule('core/backgroundtask.class.inc.php');
MetaModel::IncludeModule('core/inlineimage.class.inc.php');

View File

@@ -0,0 +1,81 @@
<?php
// Copyright (C) 2018 Combodo SARL
//
// This file is part of iTop.
//
// iTop is free software; you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// iTop 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 iTop. If not, see <http://www.gnu.org/licenses/>
/**
* <p>Stores data for {@link AttributeTagSet} fields
*
* <p>We will have an implementation for each class/field to be able to customize rights (generated in \MFCompiler::CompileClass).<br>
* Only this abstract class will exists in the DB : the implementations won't had any new field.
*
* @since 2.6 N°931 tag fields
*/
abstract class TagSetFieldData extends cmdbAbstractObject
{
public static function Init()
{
$aParams = array
(
'category' => 'bizmodel',
'key_type' => 'autoincrement',
'name_attcode' => array('tag_label'),
'state_attcode' => '',
'reconc_keys' => array('tag_code'),
'db_table' => 'priv_tagfielddata',
'db_key_field' => 'id',
'db_finalclass_field' => 'finalclass',
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeString("tag_code", array(
"allowed_values" => null,
"sql" => 'tag_code',
"default_value" => '',
"is_null_allowed" => false,
"depends_on" => array()
)));
MetaModel::Init_AddAttribute(new AttributeString("tag_label", array(
"allowed_values" => null,
"sql" => 'tag_label',
"default_value" => '',
"is_null_allowed" => false,
"depends_on" => array()
)));
MetaModel::Init_AddAttribute(new AttributeString("tag_description", array(
"allowed_values" => null,
"sql" => 'tag_description',
"default_value" => '',
"is_null_allowed" => false,
"depends_on" => array()
)));
MetaModel::Init_AddAttribute(new AttributeBoolean("is_default", array(
"allowed_values" => null,
"sql" => "is_default",
"default_value" => false,
"is_null_allowed" => false,
"depends_on" => array()
)));
MetaModel::Init_SetZListItems('details', array('tag_code', 'tag_label', 'tag_description', 'is_default'));
MetaModel::Init_SetZListItems('standard_search', array('tag_code', 'tag_label', 'tag_description', 'is_default'));
MetaModel::Init_SetZListItems('list', array('tag_code', 'tag_label', 'tag_description', 'is_default'));
}
}

View File

@@ -25,7 +25,8 @@ require_once(APPROOT.'core/moduledesign.class.inc.php');
class DOMFormatException extends Exception
{
/**
* Overrides the Exception default constructor to automatically add informations about the concerned node (path and line number)
* Overrides the Exception default constructor to automatically add informations about the concerned node (path and
* line number)
*
* @param string $message
* @param $code
@@ -47,6 +48,7 @@ class DOMFormatException extends Exception
*/
class MFCompiler
{
/** @var \ModelFactory */
protected $oFactory;
protected $aRootClasses;
@@ -280,13 +282,15 @@ class MFCompiler
}
else
{
/** @var \DOMElement $oClass */
foreach($oClasses as $oClass)
{
$sClass = $oClass->getAttribute("id");
$aAllClasses[] = $sClass;
try
{
$sCompiledCode .= $this->CompileClass($oClass, $sTempTargetDir, $sFinalTargetDir, $sRelativeDir, $oP);
$sCompiledCode .= $this->CompileClass($oClass, $sTempTargetDir, $sFinalTargetDir,
$sRelativeDir);
}
catch (DOMFormatException $e)
{
@@ -932,17 +936,15 @@ EOF
}
/**
* @param $oClass
* @param $sTempTargetDir
* @param $sFinalTargetDir
* @param $sModuleRelativeDir
* @param $oP
* @param \DOMElement $oClass
* @param string $sTempTargetDir
* @param string $sFinalTargetDir
* @param string $sModuleRelativeDir
*
* @return string
* @throws \DOMFormatException
* @throws \Exception
*/
protected function CompileClass($oClass, $sTempTargetDir, $sFinalTargetDir, $sModuleRelativeDir, $oP)
protected function CompileClass($oClass, $sTempTargetDir, $sFinalTargetDir, $sModuleRelativeDir)
{
$sClass = $oClass->getAttribute('id');
$oProperties = $oClass->GetUniqueElement('properties');
@@ -1089,17 +1091,12 @@ EOF
// Finalize class params declaration
//
$aClassParamsPHP = array();
foreach($aClassParams as $sKey => $sPHPValue)
{
$aClassParamsPHP[] = " '$sKey' => $sPHPValue,";
}
$sClassParams = implode("\n", $aClassParamsPHP);
$sClassParams = $this->GetAssociativeArrayAsPhpCode($aClassParams);
// Comment on top of the class declaration
//
$sCodeComment = $oProperties->GetChildText('comment');
// Fields
//
$oFields = $oClass->GetOptionalElement('fields');
@@ -1108,6 +1105,8 @@ EOF
$this->CompileFiles($oFields, $sTempTargetDir.'/'.$sModuleRelativeDir, $sFinalTargetDir.'/'.$sModuleRelativeDir, '');
}
$sAttributes = '';
$aTagFieldsInfo = array();
/** @var \DOMElement $oField */
foreach($this->oFactory->ListFields($oClass) as $oField)
{
try
@@ -1397,7 +1396,12 @@ EOF
$aParameters['is_null_allowed'] = $this->GetPropBoolean($oField, 'is_null_allowed', false);
$aParameters['depends_on'] = $sDependencies;
}
if ($sAttType == 'AttributeTagSet')
{
$aTagFieldsInfo[] = $sAttCode;
}
// Optional parameters (more for historical reasons)
// Added if present...
//
@@ -1786,8 +1790,10 @@ EOF
// Let's make the whole class declaration
//
$sPHP = "\n\n$sCodeComment\n";
$sClassName = $oClass->getAttribute('id');
$bIsAbstractClass = ($oProperties->GetChildText('abstract') == 'true');
$oPhpParent = $oClass->GetUniqueElement('php_parent', false);
$aRequiredFiles = array();
if ($oPhpParent)
{
$sParentClass = $oPhpParent->GetChildText('name', '');
@@ -1798,7 +1804,7 @@ EOF
$sIncludeFile = $oPhpParent->GetChildText('file', '');
if ($sIncludeFile != '')
{
$sPHP .= "\nrequire_once('$sIncludeFile'); // Implementation of the class $sParentClass\n";
$aRequiredFiles[] = $sIncludeFile;
}
//TODO fix this !!!
// $sFullPath = $this->sSourceDir.'/'.$sModuleRelativeDir.'/'.$sIncludeFile;
@@ -1811,37 +1817,44 @@ EOF
{
$sParentClass = $oClass->GetChildText('parent', 'DBObject');
}
if ($oProperties->GetChildText('abstract') == 'true')
{
$sPHP .= 'abstract class '.$oClass->getAttribute('id');
}
else
{
$sPHP .= 'class '.$oClass->getAttribute('id');
}
$sPHP .= " extends $sParentClass\n";
$sPHP .=
<<<EOF
{
public static function Init()
{
\$aParams = array
(
$sClassParams
);
MetaModel::Init_Params(\$aParams);
MetaModel::Init_InheritAttributes();
$sInitMethodCalls =
<<<EOF
$sAttributes
$sLifecycle
$sHighlightScale
$sZlists
}
$sMethods
}
$sZlists;
EOF;
// some other stuff (magical attributes like friendlyName) are done in MetaModel::InitClasses and though not present in the
// generated PHP
$sPHP = $this->GeneratePhpCodeForClass($sClassName, $sParentClass, $sClassParams, $sInitMethodCalls,
$bIsAbstractClass, $sMethods, $aRequiredFiles, $sCodeComment);
// N°931 generates TagFieldData classes for AttributeTag fields
if (!empty($aTagFieldsInfo))
{
$sTagClassParentClass = "TagSetFieldData";
$aTagClassParams = array
(
'category' => 'bizmodel',
'key_type' => 'autoincrement',
'name_attcode' => array('tag_label'),
'state_attcode' => '',
'reconc_keys' => array('tag_code'),
'db_table' => '', // no need to have a corresponding table : this class exists only for rights, no additional field
'db_key_field' => 'id',
'db_finalclass_field' => 'finalclass',
);
foreach ($aTagFieldsInfo as $sTagFieldName)
{
$sTagSuffix = $sClassName.'_'.$sTagFieldName;
$sTagClassName = 'TagSetFieldDataFor_'.$sTagSuffix;
$sTagClassParams = var_export($aTagClassParams, true);
$sPHP .= $this->GeneratePhpCodeForClass($sTagClassName, $sTagClassParentClass, $sTagClassParams);
}
}
return $sPHP;
}// function CompileClass()
}
/**
@@ -1984,7 +1997,7 @@ EOF;
$aPHPMenu[] = "\$__comp_menus__['$sMenuId']->SetParameters(array('auto_reload' => $sAutoReload));";
}
return $aPHPMenu;
} // function CompileMenu
}
/**
* Helper to compute the grant, taking any existing grant into account
@@ -2355,9 +2368,9 @@ EOF;
return $s;
}
// Transform the file references into the corresponding filename (and create the file in the relevant directory)
//
/**
* Transform the file references into the corresponding filename (and create the file in the relevant directory)
*
* @param $oNode
* @param $sTempTargetDir
* @param $sFinalTargetDir
@@ -2627,4 +2640,74 @@ EOF;
uasort($this->aSnippets[$sModuleId]['before'], array(get_class($this), 'SortOnRank'));
}
}
/**
* We can't use var_export() as we need to output some PHP code, for example `utils::GetAbsoluteUrlModulesRoot()` calls
*
* @param string[string] $aAssocArray
*
* @return string PHP declaration of the array
*/
private function GetAssociativeArrayAsPhpCode($aAssocArray)
{
$aArrayPhp = array();
foreach ($aAssocArray as $sKey => $sPHPValue)
{
$aArrayPhp[] = " '$sKey' => $sPHPValue,";
}
$sArrayPhp = implode("\n", $aArrayPhp);
return 'array('.$sArrayPhp.')';
}
/**
* @param string $sClassName
* @param string $sParentClassName
* @param string $sClassParams serialized array. Use ::GetAssociativeArrayAsPhpCode if you need to keep some PHP code calls
* @param string $sInitMethodCalls
* @param bool $bIsAbstractClass
* @param string $sMethods
*
* @param string $aRequiredFiles
* @param string $sCodeComment
*
* @return string php code for the class
*/
private function GeneratePhpCodeForClass(
$sClassName, $sParentClassName, $sClassParams, $sInitMethodCalls = '', $bIsAbstractClass = false, $sMethods = '',
$aRequiredFiles = array(), $sCodeComment = ''
) {
$sPHP = "\n\n$sCodeComment\n";
foreach ($aRequiredFiles as $sIncludeFile)
{
$sPHP .= "\nrequire_once('$sIncludeFile');\n";
}
if ($bIsAbstractClass)
{
$sPHP .= 'abstract class '.$sClassName;
}
else
{
$sPHP .= 'class '.$sClassName;
}
$sPHP .= " extends $sParentClassName\n";
$sPHP .=
<<<EOF
{
public static function Init()
{
\$aParams = $sClassParams;
MetaModel::Init_Params(\$aParams);
MetaModel::Init_InheritAttributes();
$sInitMethodCalls
}
$sMethods
}
EOF;
return $sPHP;
}
}