**/ class twIf_Widget_Object extends twIf_Object_Access { const CREATE_CAPTION = 'Create'; const EDIT_CAPTION = 'Save'; const MODE_CREATE = 'new'; const MODE_EDIT = ''; // {{{ haveData /** * Check if there was data for save/create-option supplied * * @param mixed $Handle * * @access public * @return bool **/ public static function haveData ($Handle) { if (is_object ($Handle)) { $Class = strtolower (get_class ($Handle)); $ID = $Handle->getID (); } else { $Class = strtolower ($Handle); $ID = 'new'; } if (!isset ($_POST ['obj_type']) || (md5 ($Class) != $_POST ['obj_type'])) return false; if (!isset ($_POST ['obj_id']) || (md5 ($ID) != $_POST ['obj_id'])) return false; return true; } // }}} // {{{ createObject /** * Create a new Object via a newObject-generated form * * @param string $Class Name of class to create * @param array $Fields (optional) Field-Definition * @param array $Params (optional) Which fileds pipe to constructor * @param bool $Exception (optional) Throw an exception when there are fields missing (default) * * @access public * @return object */ public function createObject ($Class, $Fields = array (), $Params = array (), $Strict = true, $Exception = true) { // Check if there was data supplied if (!self::haveData ($Class)) return null; // Check required variables $Missing = array (); foreach ($Fields as $Name=>$Field) { if (!is_array ($FieldData = self::parseFieldDef ($Name, $Field, $Class, 0))) { trigger_error (twIf_i18n::getText ('Could not parse definition for %s', $Name)); return false; } $Fields [$Name]['__pData'] = $FieldData; if (!isset ($Field ['Required']) || ($Field ['Required'] != true)) continue; if (!is_object ($Control = parent::getControl ($FieldData)) || !$Control->hasPostValue (false)) $Missing [] = array ($Name, 1, null); } if (count ($Missing) > 0) { if ($Exception) throw new twIf_Validator_Error ('Missing fields', $Missing, $Class); return false; } // Generate parameters for constructor $Flags = array (); foreach ($Params as $FieldName) if (is_object ($FieldName)) $Flags [] = $FieldName; elseif (!isset ($Fields [$FieldName])) $Flags [] = ($Strict ? '' : $FieldName); else { $Flags [] = self::getPostValue ($Fields [$FieldName]['__pData'], true); unset ($Fields [$FieldName]); } // Try to create a new instance if (!is_object ($Instance = call_user_func_array (array ($Class, 'newInstance'), $Flags))) { trigger_error (twIf_i18n::getText ('Could not create class %s', $Class)); return false; } $oObjID = $_POST ['obj_id']; $oObjType = $_POST ['obj_type']; $_POST ['obj_id'] = md5 ($Instance->getID ()); $_POST ['obj_type'] = md5 (strtolower (get_class ($Instance))); // Update callbacks on fields foreach ($Fields as $Name=>$Data) if (isset ($Data ['__pData']) && is_array ($Data ['__pData']['Write']) && ($Data ['__pData']['Write'][0] == $Class)) $Fields [$Name]['__pData']['Write'][0] = $Instance; // Treat new object as an old one :) if (($rc = self::saveObject ($Instance, $Fields)) !== false) return $Instance; trigger_error (twIf_i18n::getText ('Could not update class %s', $Class)); $Instance->remove (); $_POST ['obj_id'] = $oObjID; $_POST ['obj_type'] = $oObjType; return $rc; } // }}} // {{{ saveObject /** * Modify an existing object in database * * @param object $Object Object to modify * @param array $Fields (optional) Field-Definition * * @access public * @return bool */ public function saveObject ($Object, $Fields = array ()) { // We need an object, be sure that we have one if (!is_object ($Object)) { trigger_error (twIf_i18n::getText ('Could not save a non-object')); return false; } // Determine which class to edit $Class = get_class ($Object); if (!self::haveData ($Object)) return false; $Changed = false; foreach ($Fields as $Key=>$Field) { // Try to parse field-data if (is_array ($Field ['__pData'])) $FieldData = $Field ['__pData']; elseif (!is_array ($FieldData = self::parseFieldDef ($Key, $Field, $Object))) continue; // Get content of the field $Value = self::getPostValue ($FieldData); if ($Value === null) continue; if (!($rc = self::setFieldValue ($Object, $FieldData, $Value))) trigger_error (twIf_i18n::getText ('setFieldValue() failed')); $Changed = $Changed || ($rc && (is_array ($FieldData ['Write']) || $Object->checkUpdate ())); } // Check if there were some modifycations on the object # This fails if the object gets commited by an API-Call # $Changed = $Changed && $Object->checkUpdate (); // Commit to database if anything was changed if ($Changed) return $Object->commit (); // Return unchanged-status return null; } // }}} // {{{ newObject /** * Print Formular to create a new object * * @param string $Class Name of class to create * @param array $Fields (optional) Field-Definition * @param string $myURL (optional) Where to post data to * @param object $Exception (optional) * @param string $Caption (optional) Caption for submit-button * * @access public * @return string */ public function newObject ($Class, $Fields = array (), $myURL = null, $Exception = null, $Caption = self::CREATE_CAPTION) { return self::editObject ($Class, $Fields, $myURL, $Exception, $Caption, true); } // }}} // {{{ editObject /** * Print Formular to modify an existing object * * @param object $Object Object to modify * @param array $Fields (optional) Field-Definition * @param string $myURL (optional) Where to post data to * @param object $Exception (optional) * @param string $Caption (optional) Caption for submit-button * @param bool $AllowCreate (optional) Allow Class-Names instead of an object * * @access public * @return string */ public static function editObject ($Object, $Fields = array (), $myURL = null, $Exception = null, $Caption = self::EDIT_CAPTION, $AllowCreate = false) { // Validate input if (!is_object ($Object) && !$AllowCreate) return; if (!is_object ($Object) && !class_exists ($Object)) { trigger_error (twIf_i18n::getText ('Class %s does not exist', $Object), E_USER_WARNING); return; } // Determine which class to use if (is_object ($Object)) $Class = strtolower (get_class ($Object)); else $Class = strtolower ($Object); // Initialize $AutoSubmit = (count ($Fields) < 2); $forceSubmitBreak = false; $FieldDefs = array (); $ObjID = md5 (is_object ($Object) ? $Object->getID () : 'new'); $ClsID = md5 ($Class); $Descriptions = array (); $errorFields = array (); $buf = ''; $setFocus = ''; $hasExtended = false; $isExtended = (isset ($_REQUEST [$ClsID . '_ex']) && ($_REQUEST [$ClsID . '_ex'] == 1) ? true : false); // Detect Columns $Columns = array (); foreach ($Fields as $Name=>$Setting) { if (!isset ($Setting ['Column'])) $Setting ['Column'] = 1; if ($Setting ['Extended'] === true) { $hasExtended = true; if (!$isExtended) continue; } elseif (($Setting ['Extended'] === null) && $isExtended) continue; if (!isset ($Columns [$Setting ['Column']])) $Columns [$Setting ['Column']] = array (); $Columns [$Setting ['Column']][$Name] =& $Fields [$Name]; } # ksort ($Columns); // Detect which groups to use $ColumnGroups = array (); $maxGroups = 1; foreach ($Columns as $Col=>$Items) { $ColumnGroups [$Col] = array ('__undef__' => array ()); foreach ($Items as $Name=>$Settings) { if (isset ($Settings ['Group'])) $Gr = $Settings ['Group']; else $Gr = '__undef__'; if (!isset ($ColumnGroups [$Col][$Gr])) $ColumnGroups [$Col][$Gr] = array ('Name' => $Gr, 'Items' => array ()); $ColumnGroups [$Col][$Gr]['Items'][$Name] =& $Items [$Name]; } $maxGroups = max ($maxGroups, count ($ColumnGroups [$Col])); } // Generate output $buf .= '
\n" . '' . '\n" . '' ."\n"; if (is_object ($Exception) && is_array ($eFields = $Exception->getFields ())) foreach ($eFields as $eField) $errorFields [] = $eField [0]; for ($Group = 0; $Group < $maxGroups; $Group++) { // Load the current groups and print their headers $currentGroups = array (); $currentLevels = array (); $buf .= ''; foreach ($ColumnGroups as $Col=>$Groups) { $currentGroups [$Col] = array_shift ($ColumnGroups [$Col]); $currentLevels [$Col] = 1; $buf .= ''; } $buf .= "\n"; $ColumnSkip = array (); // Print the items do { $itemFound = false; $endRow = true; $lineBuf = ''; foreach ($currentGroups as $Col=>$Definition) { // Check if there are items on the current column-group if (count ($Definition ['Items']) < 1) { $lineBuf .= "\n";; } while ($itemFound); } // Handle end of the table if ((count ($Fields) > count ($ColumnGroups)) || $hasExtended || $forceSubmitBreak) { $buf .= "\n'; } else $buf = substr ($buf, 0, -6); $buf .= '\n" . "
' . ($currentGroups [$Col]['Name'] != '' ? '

' . twIf_i18n::getText ($currentGroups [$Col]['Name']) . '

' : '') . '
\n"; continue; } if (isset ($ColumnSkip [$Col]) && ($ColumnSkip [$Col] > 0)) { $ColumnSkip [$Col]--; continue; } $itemFound = true; // Get Item from current group // This is a little hack to maintain indexes foreach ($Definition ['Items'] as $Name=>$Setting) break; unset ($currentGroups [$Col]['Items'][$Name]); // Parse the definition if (!is_array ($FieldDef = self::parseFieldDef ($Name, $Setting, $Object, $currentLevels [$Col]))) { $lineBuf .= "\n"; $itemFound = false; continue; } $FieldDefs [$Name] = $FieldDef; // Check if the field is an extended (only shown by request) one if ($FieldDef ['Extended'] && !$isExtended) { $lineBuf .= "\n"; $itemFound = false; continue; } elseif (($FieldDef ['Extended'] === null) && $isExtended) { $lineBuf .= "\n"; $itemFound = false; continue; } // Load the default value from object $orgName = $Name; $Value = self::getFieldValue ($Object, $FieldDef); $Name = md5 (self::getFieldName ($FieldDef)); $currentLevels [$Col] = $FieldDef ['Level']; // Handle hidden fields if ($FieldDef ['Hidden'] || ($FieldDef ['Type'] == twIf_Widget_Control::TYPE_HIDDEN)) { # TODO: Find a better soultion for this! $buf .= ''; $lineBuf .= "\n"; # $itemFound = false; $endRow = false; continue; } // Prepare output $linePrefix = ''; $lineSuffix = ''; $lineControl = ''; for ($i = 0; $i < $currentLevels [$Col]; $i++) $linePrefix .= '
    '; if ($currentLevels [$Col] > 0) { $linePrefix .= '
  • '; $lineSuffix .= '
  • '; } for ($i = 0; $i < $currentLevels [$Col]; $i++) $lineSuffix .= '
'; // Handle description if (isset ($FieldDef ['Description'])) { $Hash = md5 ($FieldDef ['Description']); // Get the ID of an existing description if (isset ($Descriptions [$Hash])) { $DescrID = 1; foreach ($Descriptions as $Key=>$Descr) if ($Key == $Hash) break; else $DescrID++; // Append a new description } else { $DescrID = count ($Descriptions) + 1; $Descriptions [$Hash] = $Setting ['Description']; } } else $DescrID = 0; // Prepare output of control if (in_array ($orgName, $errorFields)) $lineControl .= '
'; // Generate the control if (is_object ($Control = parent::getControl ($FieldDef))) { if (isset ($Setting ['Enum'])) $Control->setItems ($Setting ['Enum']); if (isset ($Setting ['Prefix']) && ($Setting ['Prefix'] != '')) $lineControl .= $Setting ['Prefix'] . ' '; if ($Value == '') $Control->setValue ($Control->getPostValue ()); else $Control->setValue ($Value); $Control->setAutoSubmit ($AutoSubmit); $Control->onChange ('update_' . $ObjID . '()'); $forceSubmitBreak = $forceSubmitBreak || ($Control->getType () == twIf_Widget_Control::TYPE_ENUM_LIST); $lineControl .= $Control->generate (); if (isset ($Setting ['Unit']) && ($Setting ['Unit'] != '')) $lineControl .= ' ' . $Setting ['Unit']; if (isset ($Setting ['customURL']) && ($Setting ['customURL'] != '')) { $URL = $Setting ['customURL']; if (strpos ($URL, '?') !== false) $URL .= '&'; else $URL .= '?'; $URL .= 'id=' . urlencode ($Name); $lineControl .= '[...]"; } } else $lineControl .= '' . twIf_i18n::getText ('Control-Handle missing') . ''; if (in_array ($orgName, $errorFields)) $lineControl .= '
'; if ($FieldDef ['Focus']) $setFocus = $Name; // Append the control $lineCaption = '

'; if ($FieldDef ['Type'] == twIf_Widget_Control::TYPE_BOOL_CHECKBOX) { $Left = $lineControl; $Right = $lineCaption; $lClass = 'twIfInput'; $rClass = 'twIfLabel'; } else { $Left = $lineCaption; $Right = $lineControl; $lClass = 'twIfLabel'; $rClass = 'twIfInput'; } if ($Setting ['Rows'] > 1) { $ColumnSkip [$Col] = $Setting ['Rows'] - 1; $lineBuf .= '
' . $linePrefix . $lineCaption . $lineControl . $lineSuffix . ''; } elseif ($FieldDef ['Wrap']) { $lineBuf .= '' . $linePrefix . $Left . ' ' . $Right . $lineSuffix . ''; } else $lineBuf .= '' . $linePrefix . $Left . $lineSuffix . '' . $Right . ''; } if ($itemFound && $endRow) $buf .= $lineBuf . "
"; // Handle extended-button if ($hasExtended) $buf .= '' . ($isExtended ? '« ' : '» ') . twIf_i18n::getText ($isExtended ? 'Collapse' : 'Uncollapse') . ''; $buf .= '' . "\n" . "
\n"; // Handle additional javascripts $buf .= "\n
\n"; // Check if any of the fields was marked as required foreach ($Fields as $Field) if ($Field ['Required']) { $buf .= '

* ' . twIf_i18n::getText ('Required') . "

\n"; break; } if (count ($Descriptions) > 0) { $buf .= '

\n"; } return $buf; } // }}} } ?>