obj =& $obj; $this -> name = $relationName; $this -> config = $obj -> getConfig("LSrelation.$relationName"); if (!is_array($this -> config) || !$this -> checkConfig()) { $this -> config = null; LSerror :: addErrorCode( 'LSrelation_02', array( 'relation' => $relationName, 'LSobject' => $obj -> getType() ) ); } } /** * Allow conversion of LSrelation to string * * @retval string The string representation of the LSrelation */ public function __toString() { return " name." on ".$this -> obj -> toString(false).">"; } /** * Return a configuration parameter (or default value) * * @param[] $param The configuration parameter * @param[] $default The default value (default : null) * @param[] $cast Cast resulting value in specific type (default : disabled) * * @retval mixed The configuration parameter value or default value if not set **/ public function getConfig($param, $default=null, $cast=null) { // Check relation is correctly configured if (!$this -> correctly_configured) return false; return LSconfig :: get($param, $default, $cast, $this -> config); } /** * Get relation info * * @param[in] $key string The info name * * @retval mixed The info value */ public function __get($key) { switch ($key) { case 'name': return $this -> name; case 'correctly_configured': return boolval($this -> config); case 'LSobject': case 'linkAttribute': case 'linkAttributeValue': case 'linkAttributeOtherValues': case 'list_function': case 'getkeyvalue_function': case 'update_function': case 'remove_function': case 'rename_function': case 'canEdit_function': case 'canEdit_attribute': return $this -> getConfig($key); case 'linkAttributeValues': $linkAttributeValues = ensureIsArray($this -> linkAttributeOtherValues); if ($this -> linkAttributeValue) $linkAttributeValues[] = $this -> linkAttributeValue; return $linkAttributeValues; case 'relatedEditableAttribute': return $this -> getConfig( 'canEdit_attribute', $this -> getConfig('linkAttribute', false) ); } // Unknown key, log warning self :: log_warning("__get($key): invalid property requested\n".LSlog :: get_debug_backtrace_context()); } /** * Check relation configuration * * @retval boolean True if relation is properly configured, False otherwise */ public function checkConfig() { // Check LSobject parameter if (!$this -> LSobject) { LSerror :: addErrorCode( 'LSrelation_07', array( 'parameter' => 'LSobject', 'relation' => $this -> name, 'LSobject' => $this -> LSobject ) ); return false; } // Load related object type if (!LSsession :: loadLSobject($this -> LSobject)) { LSerror :: addErrorCode( 'LSrelation_04', array( 'relation' => $this -> name, 'LSobject' => $this -> LSobject ) ); return false; } // Check if it's a simple relation if ($this -> linkAttribute && $this -> linkAttributeValue) { // Check linkAttribute refered to an existing related object type attribute if (!call_user_func(array($this -> LSobject, 'hasAttr'), $this -> linkAttribute)) { LSerror :: addErrorCode( 'LSrelation_08', array( 'parameter' => 'linkAttribute', 'relation' => $this -> name, 'LSobject' => $this -> LSobject ) ); return false; } // Check linkAttributeValue if ($this -> linkAttributeValue != 'dn' && !$this -> obj -> hasAttr($this -> linkAttributeValue)) { LSerror :: addErrorCode( 'LSrelation_08', array( 'parameter' => 'linkAttributeValue', 'relation' => $this -> name, 'LSobject' => $this -> LSobject ) ); return false; } return true; } // Advanced relation: check all required parameters refered to related objects // methods $required_parameters = array( 'list_function', 'getkeyvalue_function', 'update_function', 'remove_function', 'rename_function', 'canEdit_function', ); foreach($required_parameters as $p) { // Check parameter is defined if (!$this -> $p) { LSerror :: addErrorCode( 'LSrelation_07', array( 'parameter' => $p, 'relation' => $this -> name, 'LSobject' => $this -> LSobject ) ); return false; } // Check parameter refered to an existing related object class method if (!method_exists($this -> LSobject, $this -> $p)) { LSerror :: addErrorCode( 'LSrelation_01', array( 'parameter' => $p, 'function' => $this -> $p, 'LSobject' => $this -> LSobject, 'relation' => $this -> name, ) ); return false; } } return true; } /** * Check a relation exist * * @param[in] $object_type string The object type * @param[in] $relation_name string The relation name * * @retval boolean True if relation exist, false otherwise */ public static function exists($object_type, $relation_name) { if ($object_type && LSsession :: loadLSobject($object_type)) { return is_array(LSconfig :: get("LSobjects.$object_type.LSrelation.$relation_name")); } return false; } /** * Get relation name * * @retval string The relation name */ public function getName() { return $this -> name; } /** * Check if user can edit this relation * * @retval boolean True if user can edit this relation, false otherwise */ public function canEdit() { return LSsession :: relationCanEdit($this -> obj -> getValue('dn'),$this -> obj -> getType(),$this -> name); } /** * Check if user can create a related object * * @retval boolean True if user can create a related object, false otherwise */ public function canCreate() { return LSsession :: canCreate($this -> LSobject); } /** * List related objects * * @retval array|false An array of related objects (LSldapObject), of false in case of error */ public function listRelatedObjects() { // Check relation is correctly configured if (!$this -> correctly_configured) return false; // Load related object type if (!LSsession :: loadLSobject($this -> LSobject)) { LSerror :: addErrorCode( 'LSrelation_04', array( 'relation' => $this -> name, 'LSobject' => $this -> LSobject ) ); return false; } // Instanciate related object $objRel = new $this -> LSobject(); // Use list_function if ($this -> list_function) { if (method_exists($this -> LSobject, $this -> list_function)) { return call_user_func_array( array($objRel, $this -> list_function), array(&$this -> obj) ); } LSerror :: addErrorCode( 'LSrelation_01', array( 'parameter' => 'list_function', 'function' => $this -> list_function, 'LSobject' => $objRel -> getType(), 'relation' => $this -> name, ) ); return False; } // Use linkAttribute & linkAttributeValue if ($this -> linkAttribute && $this -> linkAttributeValue) { return $objRel -> listObjectsInRelation( $this -> obj, $this -> linkAttribute, $this -> obj -> getType(), $this -> linkAttributeValues ); } // Configuration problem LSerror :: addErrorCode( 'LSrelation_05', array( 'relation' => $this -> name, 'LSobject' => $this -> LSobject, 'action' => _('listing related objects') ) ); return false; } /** * Get the value to store to created the relation with $this -> obj * * @retval array List of value of the link attribute */ public function getRelatedKeyValue() { // Check relation is correctly configured if (!$this -> correctly_configured) return false; // Load related object type if (!LSsession :: loadLSobject($this -> LSobject)) { LSerror :: addErrorCode( 'LSrelation_04', array( 'relation' => $this -> name, 'LSobject' => $this -> LSobject ) ); return false; } // Instanciate related object $objRel = new $this -> LSobject(); // Use getkeyvalue_function if ($this -> getkeyvalue_function) { if (method_exists($this -> LSobject, $this -> getkeyvalue_function)) { return call_user_func_array( array($objRel, $this -> getkeyvalue_function), array(&$this -> obj) ); } LSerror :: addErrorCode( 'LSrelation_01', array( 'parameter' => 'getkeyvalue_function', 'function' => $this -> getkeyvalue_function, 'LSobject' => $objRel -> getType(), 'relation' => $this -> name, ) ); return false; } // Use linkAttribute & linkAttributeValue if ($this -> linkAttribute && $this -> linkAttributeValue) { return $objRel -> getObjectKeyValueInRelation( $this -> obj, $this -> obj -> getType(), $this -> linkAttributeValue ); } // Configuration problem LSerror :: addErrorCode( 'LSrelation_05', array( 'relation' => $this -> name, 'LSobject' => $this -> LSobject, 'action' => _('getting key value') ) ); return false; } /** * Check if user can edit the relation with the specified object * * @param[in] &$objRel LSldapObject A reference to the related object * * @retval boolean True if user can edit the relation with the specified object, false otherwise */ public function canEditRelationWithObject(&$objRel) { // Check relation is correctly configured if (!$this -> correctly_configured) return false; if (!$this -> canEdit()) return; // Use canEdit_function if ($this -> canEdit_function) { if (method_exists($objRel, $this -> canEdit_function)) { return call_user_func(array($objRel, $this -> canEdit_function)); } LSerror :: addErrorCode( 'LSrelation_01', array( 'parameter' => 'canEdit_function', 'function' => $this -> canEdit_function, 'LSobject' => $objRel -> getType(), 'relation' => $this -> name, ) ); return False; } // Use related editable attribute if ($this -> relatedEditableAttribute) { return LSsession :: canEdit( $objRel -> getType(), $objRel -> getDn(), $this -> relatedEditableAttribute ); } // Configuration problem LSerror :: addErrorCode( 'LSrelation_05', array( 'relation' => $this -> name, 'LSobject' => $this -> LSobject, 'action' => _('checking right on relation with specific object') ) ); return false; } /** * Remove relation with the specified object * * @param[in] &$objRel LSldapObject A reference to the related object * * @retval boolean True if relation removed, false otherwise */ public function removeRelationWithObject(&$objRel) { // Check relation is correctly configured if (!$this -> correctly_configured) return false; // Use remove_function if ($this -> remove_function) { if (method_exists($this -> LSobject, $this -> remove_function)) { return call_user_func_array( array($objRel, $this -> remove_function), array(&$this -> obj) ); } LSerror :: addErrorCode( 'LSrelation_01', array( 'parameter' => 'remove_function', 'function' => $this -> remove_function, 'LSobject' => $objRel -> getType(), 'relation' => $this -> name, ) ); return False; } // Use linkAttribute & linkAttributeValue if ($this -> linkAttribute && $this -> linkAttributeValue) { return $objRel -> deleteOneObjectInRelation($this -> obj, $this -> linkAttribute, $this -> obj -> getType(), $this -> linkAttributeValue, null, $this -> linkAttributeValues); } // Configuration problem LSerror :: addErrorCode( 'LSrelation_05', array( 'relation' => $this -> name, 'LSobject' => $this -> LSobject, 'action' => _('removing relation with specific object') ) ); return false; } /** * Rename relation with the specified object * * @param[in] &$objRel LSldapObject A reference to the related object * @param[in] $oldKeyValue string The old key value of the relation * * @retval boolean True if relation rename, false otherwise */ public function renameRelationWithObject(&$objRel, $oldKeyValue) { // Check relation is correctly configured if (!$this -> correctly_configured) return false; // Use rename_function if ($this -> rename_function) { if (method_exists($objRel,$this -> rename_function)) { return call_user_func_array(array($objRel, $this -> rename_function), array(&$this -> obj, $oldKeyValue)); } LSerror :: addErrorCode( 'LSrelation_01', array( 'parameter' => 'rename_function', 'function' => $this -> rename_function, 'LSobject' => $objRel -> getType(), 'relation' => $this -> name, ) ); return False; } // Use linkAttribute & linkAttributeValue if ($this -> linkAttribute && $this -> linkAttributeValue) { return $objRel -> renameOneObjectInRelation( $this -> obj, $oldKeyValue, $this -> linkAttribute, $this -> obj -> getType(), $this -> linkAttributeValue ); } // Configuration problem LSerror :: addErrorCode( 'LSrelation_05', array( 'relation' => $this -> name, 'LSobject' => $this -> LSobject, 'action' => _('checking right on relation with specific object') ) ); return false; } /** * Update relation with the specified DN objects list * * @param[in] $listDns array Array of DN of the related objects * * @retval boolean True if relations updated, false otherwise */ public function updateRelations($listDns) { // Check relation is correctly configured if (!$this -> correctly_configured) return false; // Load related objects type if (!LSsession :: loadLSobject($this -> LSobject)) { LSerror :: addErrorCode( 'LSrelation_04', array( 'relation' => $this -> name, 'LSobject' => $this -> LSobject ) ); return false; } // Instanciate related object $objRel = new $this -> LSobject(); // Use update_function if ($this -> update_function) { if (method_exists($objRel, $this -> update_function)) { return call_user_func_array( array($objRel, $this -> update_function), array(&$this -> obj, $listDns) ); } LSerror :: addErrorCode( 'LSrelation_01', array( 'parameter' => 'update_function', 'function' => $this -> update_function, 'LSobject' => $objRel -> getType(), 'relation' => $this -> name, ) ); return false; } // Use linkAttribute & linkAttributeValue if ($this -> linkAttribute && $this -> linkAttributeValue) { return $objRel -> updateObjectsInRelation( $this -> obj, $listDns, $this -> linkAttribute, $this -> obj -> getType(), $this -> linkAttributeValue, null, $this -> linkAttributeValues ); } // Configuration problem LSerror :: addErrorCode( 'LSrelation_05', array( 'relation' => $this -> name, 'LSobject' => $this -> LSobject, 'action' => _('updating relations') ) ); return false; } /* * Load display dependencies * * @retval void */ public static function loadDependenciesDisplay() { if (LSsession :: loadLSclass('LSselect')) { LSselect :: loadDependenciesDisplay(); } LStemplate :: addJSscript('LSrelation.js'); LStemplate :: addCssFile('LSrelation.css'); LStemplate :: addJSconfigParam('LSrelation_labels', array( 'close_confirm_text' => _('Do you really want to delete'), 'close_confirm_title' => _('Warning'), 'close_confirm_validate' => _('Delete') )); } /* * Load LSrelations information of an object to display it on LSview. * * LSrelations information are provided to template by usind LSrelations variable. * * @param[in] $object LSldapObject L'objet dont on cherche les LSrelations * * @retval void */ public static function displayInLSview($object) { if (!($object instanceof LSldapObject)) return; if (!is_array($object -> getConfig('LSrelation'))) return; $LSrelations=array(); $LSrelation_JSparams=array(); foreach($object -> getConfig('LSrelation') as $relationName => $relationConf) { // Check user access if (!LSsession :: relationCanAccess($object -> getValue('dn'), $object->getType(), $relationName)) { self :: log_debug("User have no access to relation $relationName of ".$object->getType()); continue; } $return=array( 'label' => __($relationConf['label']), 'LSobject' => $relationConf['LSobject'] ); if (isset($relationConf['emptyText'])) { $return['emptyText'] = __($relationConf['emptyText']); } else { $return['emptyText'] = _('No object.'); } $id=rand(); $return['id']=$id; $LSrelation_JSparams[$id]=array( 'emptyText' => $return['emptyText'] ); $_SESSION['LSrelation'][$id] = array( 'relationName' => $relationName, 'objectType' => $object -> getType(), 'objectDn' => $object -> getDn(), ); $relation = new LSrelation($object, $relationName); if (!$relation -> correctly_configured) continue; if ($relation -> canEdit()) { $return['actions'][] = array( 'label' => _('Modify'), 'url' => "object/select/$id", 'action' => 'modify', 'class' => 'LSrelation_modify', 'data' => array( 'relation-id' => $id, ) ); } if ($relation -> canCreate()) { $return['actions'][] = array( 'label' => _('New'), 'url' => 'object/'.$relationConf['LSobject'].'/create?LSrelation='.$relationName.'&relatedLSobject='.$object->getType().'&relatedLSobjectDN='.urlencode($object -> getValue('dn')), 'action' => 'create', 'class' => null, ); } $list = $relation -> listRelatedObjects(); if (is_array($list)) { foreach($list as $o) { $return['objectList'][] = array( 'text' => $o -> getDisplayName( LSconfig :: get('display_name_format', null, null, $relationConf), true ), 'dn' => $o -> getDn(), 'canEdit' => $relation -> canEditRelationWithObject($o) ); } } else { $return['objectList']=array(); } $LSrelations[]=$return; } self :: loadDependenciesDisplay(); LStemplate :: assign('LSrelations',$LSrelations); LStemplate :: addJSconfigParam('LSrelations',$LSrelation_JSparams); } /* * AJAX methods */ /** * Helper to check AJAX method call and instanciate corresponding * LSldapObject and LSrelation objects. * * @param[in] &$data array Reference to AJAX returned data array * @param[in] $additional_parameters array|string|null List of additional required parameter * * @retval array|false Array with LSobject and LSrelation */ public static function _ajax_check_call(&$data, &$conf, &$object, &$relation, $additional_required_parameters=null) { $data['success'] = false; // Check parameters if (!isset($_REQUEST['id'])) { self :: log_warning("Parameter 'id' is missing."); LSerror :: addErrorCode('LSsession_12'); return false; } // Check additional required parameters if ($additional_required_parameters) { foreach(ensureIsArray($additional_required_parameters) as $p) { if (!isset($_REQUEST[$p])) { self :: log_warning("Parameter '$p' is missing."); LSerror :: addErrorCode('LSsession_12'); return false; } $data[$p] = $_REQUEST[$p]; } } // Check relation exists in session if (!isset($_SESSION['LSrelation'][$_REQUEST['id']])) { self :: log_warning("No relation '".$_REQUEST['id']."' in session"); return false; } // Load object type $conf = $_SESSION['LSrelation'][$_REQUEST['id']]; if (!LSsession ::loadLSobject($conf['objectType'])) { self :: log_warning("Fail to load '".$conf['objectType']."'"); return false; } $data['id'] = $_REQUEST['id']; // Check relation exists if (!self :: exists($conf['objectType'], $conf['relationName'])) { self :: log_warning("Relation '".$conf['relationName']."' not found in ".$conf['objectType']." configuration"); return false; } // Instanciate object and load its data $object = new $conf['objectType'](); if (!$object -> loadData($conf['objectDn'])) { self :: log_warning("Fail to load data of '".$conf['objectDn']."'"); return false; } // Instanciate relation $relation = new LSrelation($object, $conf['relationName']); // Check relation is correctly configured if (!$relation -> correctly_configured) return false; // Check user access to it relation if (!$relation -> canEdit()) { LSerror :: addErrorCode('LSsession_11'); return false; } self :: log_debug("_ajax_check_call(): ok"); return true; } /** * Init LSselect for a relation * * @param[in] &$data Reference to returned data array * * @retval void */ public static function ajax_initSelection(&$data) { $conf = null; $object = null; $relation = null; if (!self :: _ajax_check_call($data, $conf, $object, $relation, 'href')) { return; } // Load LSselect if(!LSsession :: loadLSclass('LSselect', null, true)) { return; } // List related objects $list = $relation -> listRelatedObjects(); if (!is_array($list)) { self :: log_warning('Fail to list related objects'); return; } // Forge selected object list for LSselect $selected_objects = array(); foreach($list as $o) { $selected_objects[$o -> getDn()] = array( 'object_type' => $o -> getType(), 'editableAttr' => $relation -> relatedEditableAttribute, ); } // Init LSselect LSselect :: init( $_REQUEST['id'], array ( $relation -> LSobject => array( 'object_type' => $relation -> LSobject, ) ), true, $selected_objects ); // Set success $data['success'] = true; } /** * Update related object from LSselect result * * @param[in] &$data Reference to returned data array * * @retval void */ public static function ajax_updateFromSelection(&$data) { $conf = null; $object = null; $relation = null; if (!self :: _ajax_check_call($data, $conf, $object, $relation)) { return; } $LSobjectInRelation = $object->getConfig("LSrelation.".$conf['relationName'].".LSobject"); $relationConf = $object->getConfig("LSrelation.".$conf['relationName']); // Load LSselect if(!LSsession :: loadLSclass('LSselect', null, true)) { return; } // Retrieve selected object from LSselect $selected_objects = LSselect :: getSelectedObjects($_REQUEST['id']); if (!is_array($selected_objects)) { self :: log_warning("Fail to retrieve selected object from LSselect"); return; } self :: log_debug('Selected objects: '.varDump($selected_objects)); // Update related objects if (!$relation -> updateRelations(array_keys($selected_objects))) { LSerror :: addErrorCode('LSrelation_03', $conf['relationName']); self :: log_warning("Fail to update objects in relation"); return; } self :: log_debug('Related objects updated'); // List related objects $list = $relation -> listRelatedObjects(); if (is_array($list) && !empty($list)) { $data['html']=""; foreach($list as $o) { if ($relation -> canEditRelationWithObject($o)) { $class=' LSrelation_editable'; } else { $class=''; } $data['html'].= "
  • getDn()."'>".$o -> getDisplayName(NULL,true)."
  • \n"; } } else { if (isset($relationConf['emptyText'])) { $data['html'] = "
  • ".__($relationConf['emptyText'])."
  • \n"; } else { $data['html'] = "
  • "._('No object.')."
  • \n"; } } $data['success'] = true; } /** * Remove related object specify by DN * * @param[in] &$data Reference to returned data array * * @retval void */ public static function ajax_deleteByDn(&$data) { $conf = null; $object = null; $relation = null; if (!self :: _ajax_check_call($data, $conf, $object, $relation, 'dn')) { return; } // List related objects $list = $relation -> listRelatedObjects(); if (!is_array($list)) { self :: log_warning('Fail to list related objects'); LSerror :: addErrorCode('LSrelation_03',$conf['relationName']); return; } // For each related objects: // - check if DN match // - check user can edit relation with specific object // - remove relation $found = false; foreach($list as $o) { if($o -> getDn() == $_REQUEST['dn']) { if (!$relation -> canEditRelationWithObject($o)) { LSerror :: addErrorCode('LSsession_11'); return; } if (!$relation -> removeRelationWithObject($o)) { LSerror :: addErrorCode('LSrelation_03', $conf['relationName']); return; } else { $found = true; } break; } } // Check object found if (!$found) { self :: log_warning("Object '".$_REQUEST['dn']."' not found in related objects list."); LSerror :: addErrorCode('LSrelation_03', $conf['relationName']); return; } // Set success $data['dn'] = $_REQUEST['dn']; $data['success'] = true; } } /** * Error Codes **/ LSerror :: defineError('LSrelation_01', ___("LSrelation : Invalid parameter '%{parameter}' of the relation %{relation}: objects %{LSobject} have no function '%{function}'.") ); LSerror :: defineError('LSrelation_02', ___("LSrelation : Relation %{relation} of object type %{LSobject} unknown.") ); LSerror :: defineError('LSrelation_03', ___("LSrelation : Error during relation update of the relation %{relation}.") ); LSerror :: defineError('LSrelation_04', ___("LSrelation : Object type %{LSobject} unknown (Relation : %{relation}).") ); LSerror :: defineError('LSrelation_05', ___("LSrelation : Incomplete configuration for LSrelation %{relation} of object type %{LSobject} for action : %{action}.") ); LSerror :: defineError('LSrelation_06', ___("LSrelation : Invalid editable attribute for LSrelation %{relation} with LSobject %{LSobject}.") ); LSerror :: defineError('LSrelation_07', ___("LSrelation : The configuration parameter '%{parameter}' of the relation %{relation} of %{LSobject} is missing.") ); LSerror :: defineError('LSrelation_08', ___("LSrelation : The configuration parameter '%{parameter}' of the relation %{relation} of %{LSobject} is invalid.") );