Commit f14a91e8 authored by Côme Bernigaud's avatar Côme Bernigaud Committed by Benoit Mortier
Browse files

Fixes: #1922 Moving foreignKey handling to plugin

parent d7c94fc4
......@@ -28,8 +28,8 @@
/*!
* \brief This class contains all function to copy and paste
*/
class CopyPasteHandler {
class CopyPasteHandler
{
var $config;
var $current;
......@@ -57,9 +57,9 @@ class CopyPasteHandler {
*/
function CopyPasteHandler(&$config)
{
$this->config = &$config;
$this->current = NULL;
$this->queue = array();
$this->config = &$config;
$this->current = NULL;
$this->queue = array();
}
......@@ -185,24 +185,20 @@ class CopyPasteHandler {
$this->objects_to_fix = array();
$this->disallowed_objects = array();
/* Put each queued object in one of the above arrays
*/
/* Put each queued object in one of the above arrays */
foreach ($this->queue as $key => $entry) {
/* Update entries on demand
*/
/* Update entries on demand */
if (!isset($entry['object'])) {
$entry = $this->load_entry_from_queue($entry, $base);
$this->queue[$key] = $entry;
}
$msgs = $entry['object']->check();
/* To copy an object we require full read access to the object category
*/
/* To copy an object we require full read access to the object category */
$copy_acl = preg_match("/r/", $ui->has_complete_category_acls($entry['dn'], $entry['tab_acl_category']));
/* In order to copy an object we require read an delete acls
*/
/* In order to copy an object we require read an delete acls */
$cut_acl = preg_match("/d/", $ui->has_complete_category_acls($entry['dn'], $entry['tab_acl_category']));
$cut_acl &= preg_match("/r/", $ui->has_complete_category_acls($entry['dn'], $entry['tab_acl_category']));
......@@ -227,40 +223,29 @@ class CopyPasteHandler {
$this->require_update = FALSE;
}
/* Save objects that can be pasted directly
*/
/* Save objects that can be pasted directly */
if (count($this->clean_objects)) {
$this->save_object();
foreach ($this->clean_objects as $key => $entry) {
/* Remove from queue -> avoid saving twice */
unset($this->queue[$key]);
unset($this->clean_objects[$key]);
/* Load next queue entry */
$this->current = $entry;
$this->lastdn = $this->current['object']->dn;
$this->current['object']->save();
$this->handleReferences();
$this->save_current($entry);
}
$this->current = FALSE;
}
/* Save edited entry and force loading new one
*/
/* Save edited entry and force loading new one */
if (isset($this->current['object'])) {
$this->current['object']->save_object();
}
/* Save current object if edition is finished */
if (isset($_POST['edit_finish']) && $this->current) {
$msgs = $this->current['object']->check();
/* Load next queue entry */
if (!count($msgs)) {
$this->current['object']->save();
$this->handleReferences();
$this->lastdn = $this->current['object']->dn;
$this->current = FALSE;
$this->save_current();
} else {
foreach ($msgs as $msg) {
msg_dialog::display(_("Error"), $msg, ERROR_DIALOG);
......@@ -268,14 +253,13 @@ class CopyPasteHandler {
}
}
/* Display a list of all pastable entries
*/
/* Display a list of all pastable entries */
if ($this->current || count($this->objects_to_fix)) {
$this->save_object();
if (!$this->current) {
$key = key($this->objects_to_fix);
if (isset($this->objects_to_fix[$key])) {
$this->current = $this->objects_to_fix[$key];
if ($key !== NULL) {
$this->current = $this->objects_to_fix[$key];
unset($this->objects_to_fix[$key]);
unset($this->queue[$key]);
}
......@@ -300,6 +284,17 @@ class CopyPasteHandler {
return "";
}
private function save_current($object = NULL)
{
if ($objet !== NULL) {
$this->current = $object;
}
$this->lastdn = $this->current['object']->dn;
$this->current['object']->save();
$this->handleReferences();
$this->current = FALSE;
}
/*!
* \brief Get the last endited entry
......@@ -362,29 +357,6 @@ class CopyPasteHandler {
$role->save();
}
}
// Update groups
if (isset($this->current['object']->uid) && !empty($this->current['object']->uid)) {
$ldap = $this->config->get_ldap_link();
$ldap->cd($this->config->current['BASE']);
$ldap->cat($src_dn);
$attrs = $ldap->fetch();
if (isset($attrs['uid'][0])) {
$suid = $attrs['uid'][0];
$uid = $this->current['object']->uid;
$groups = get_sub_list("(&(objectClass=posixGroup)(memberUid={$suid}))",
"group", array(get_ou("groupRDN")), $this->config->current['BASE'], array("dn"), GL_SUBSEARCH | GL_NO_ACL_CHECK);
// Walk through all POSIX groups
foreach ($groups as $group) {
$o_group = new group($this->config, $group['dn']);
$o_group->addUser($uid);
$o_group->save();
}
}
}
}
/*!
......
......@@ -1188,6 +1188,7 @@ class plugin
$ui->reset_acl_cache();
}
$this->handleForeignKeys($src_dn, $dst_dn);
return TRUE;
}
......@@ -1202,6 +1203,213 @@ class plugin
}
}
function handleForeignKeys ($olddn = NULL, $newdn = NULL, $mode = 'move')
{
if (($olddn !== NULL) && ($olddn == $newdn)) {
return;
}
$this->browseForeignKeys(
'handle_'.$mode,
$olddn,
$newdn
);
}
function browseForeignKeys($mode, $param1 = NULL, $param2 = NULL)
{
if (preg_match('/^handle_/', $mode)) {
$olddn = $param1;
$newdn = $param2;
$classes = array(get_class($this));
} elseif ($mode == 'references') {
$classes = array_keys($this->parent->by_object);
}
// We group by objetType concerned
$foreignRefs = array();
foreach ($classes as $tabclass) {
$infos = pluglist::pluginInfos($tabclass);
foreach ($infos['plForeignRefs'] as $field => $refs) {
if (preg_match('/^handle_/', $mode)) {
if ($newdn !== NULL) {
// Move action
if (($field != 'dn') && ($mode == 'handle_move')) {
// We only change dn
continue;
}
} elseif ($olddn === NULL) {
// Edit action
if ($field == 'dn') {
// dn did not change
continue;
} elseif (!$this->attributeHaveChanged($field)) {
// only look at changed attributes
continue;
}
}
// else = delete action, all fields are concerned, nothing to do here
}
foreach ($refs as $ref) {
$class = $ref[0];
$ofield = $ref[1];
$filter = $ref[2];
$cinfos = pluglist::pluginInfos($class);
foreach ($cinfos['plObjectType'] as $key => $objectType) {
if (!is_numeric($key)) {
$objectType = $key;
}
if (preg_match('/^handle_/', $mode)) {
if ($field == 'dn') {
$oldvalue = $olddn;
$newvalue = $newdn;
} elseif (($olddn !== NULL) && ($newdn === NULL)) {
$oldvalue = $this->attributeInitialValue($field);
$newvalue = NULL;
} else {
$oldvalue = $this->attributeInitialValue($field);
$newvalue = $this->attributeValue($field);
}
$foreignRefs[$objectType]['refs'][$class][$ofield] =
array(
'field' => $field,
'oldvalue' => $oldvalue,
'newvalue' => $newvalue,
'tab' => $tabclass,
);
$filter = plugin::tpl_parse_string($filter, array('oldvalue' => $oldvalue, 'newvalue' => $newvalue));
} elseif ($mode == 'references') {
$foreignRefs[$objectType]['refs'][$class]['name'] = $cinfos['plShortName'];
$foreignRefs[$objectType]['refs'][$class]['fields'][$ofield] =
array(
'tab' => $tabclass,
'tabname' => $this->parent->by_name[$tabclass],
'field' => $field,
'value' => $this->parent->by_object[$tabclass]->$field,
);
$filter = plugin::tpl_parse_string($filter, array('oldvalue' => $this->parent->by_object[$tabclass]->$field));
}
if (!preg_match('/^\(.*\)$/', $filter)) {
$filter = '('.$filter.')';
}
$foreignRefs[$objectType]['filters'][$filter] = $filter;
}
}
}
}
$refs = array();
// For each concerned objectType
foreach ($foreignRefs as $objectType => $tabRefs) {
// Compute filter
$filters = array_values($tabRefs['filters']);
$filter = '(|'.join($filters).')';
// Search objects
try {
$objects = objects::ls($objectType, array('dn' => 'raw'), NULL, $filter);
} catch (EmptyFilterException $e) {
continue;
}
// For each object of this type
foreach (array_keys($objects) as $dn) {
// Build the object
$tabobject = objects::open($dn, $objectType);
if (preg_match('/^handle_/', $mode)) {
// For each tab concerned
foreach ($tabRefs['refs'] as $tab => $fieldRefs) {
// If the tab is activated on this object
if (isset($tabobject->by_object[$tab])) {
// For each field
foreach ($fieldRefs as $ofield => $field) {
// call plugin::foreignKeyUpdate(ldapname, oldvalue, newvalue, source) on the object
$tabobject->by_object[$tab]->foreignKeyUpdate(
$ofield,
$field['oldvalue'],
$field['newvalue'],
array(
'CLASS' => $field['tab'],
'FIELD' => $field['field'],
'MODE' => preg_replace('/^handle_/', '', $mode),
)
);
}
$tabobject->by_object[$tab]->save_object();
$tabobject->by_object[$tab]->save();
}
}
} elseif ($mode == 'references') {
// For each tab concerned
foreach ($tabRefs['refs'] as $tab => $tab_infos) {
// If the tab is activated on this object
if (isset($tabobject->by_object[$tab])) {
// For each field
foreach ($tab_infos['fields'] as $ofield => $field) {
if ($tabobject->by_object[$tab]->foreignKeyCheck(
$ofield,
$field['value'],
array('CLASS' => $field['tab'], 'FIELD' => $field['field'])
)) {
if (!isset($refs[$dn])) {
$refs[$dn] = array(
'link' => '',
'tabs' => array(),
);
try {
$refs[$dn]['link'] = objects::link($dn, $objectType);
} catch (Exception $e) {
trigger_error("Could not create link to $dn: ".$e->getMessage());
$refs[$dn]['link'] = $dn;
}
}
if (!isset($refs[$dn]['tabs'][$tab])) {
$refs[$dn]['tabs'][$tab] = array(
'link' => '',
'fields' => array(),
);
try {
$refs[$dn]['tabs'][$tab]['link'] = objects::link($dn, $objectType, "tab_$tab", sprintf(_('Tab "%s"'), $tab_infos['name']));
} catch (Exception $e) {
trigger_error("Could not create link to $dn $tab: ".$e->getMessage());
$refs[$dn]['tabs'][$tab]['link'] = $tab;
}
}
$refs[$dn]['tabs'][$tab]['fields'][$ofield] = $field;
}
}
}
}
}
}
}
if ($mode == 'references') {
return $refs;
}
}
protected function attributeValue($field)
{
return $this->$field;
}
protected function attributeInitialValue($field)
{
die("Foreign key was declared but there is no method attributeInitialValue to handle it!".
" Class:".get_class($this).", Field:$field");
}
protected function attributeHaveChanged($field)
{
die("Foreign key was declared but there is no method attributeHaveChanged to handle it!".
" Class:".get_class($this).", Field:$field");
}
/*
* Source is an array like this:
* array(
* 'CLASS' => class,
* 'FIELD' => field,
* 'MODE' => mode
* )
* mode being either 'copy' or 'move', defaults to 'move'
*/
function foreignKeyUpdate ($field, $oldvalue, $newvalue, $source)
{
die("Foreign key was declared but there is no method foreignKeyUpdate to handle it!".
......@@ -1263,6 +1471,12 @@ class plugin
*/
function handle_post_events($mode, $addAttrs = array())
{
/* Update foreign keys */
if ($mode == 'remove') {
$this->handleForeignKeys($this->dn, NULL);
} elseif (($mode == 'add') || ($mode == 'modify')) {
$this->handleForeignKeys();
}
return $this->handle_hooks('POST', $mode, $addAttrs);
}
......
......@@ -202,20 +202,20 @@ class ACLsAssignmentAttribute extends DialogOrderedArrayAttribute
function foreignKeyUpdate($oldvalue, $newvalue, $source)
{
foreach ($this->value as $key => &$value) {
if (($source[0] == 'aclRole') && ($value['role'] == $oldvalue)) {
if (($source['CLASS'] == 'aclRole') && ($value['role'] == $oldvalue)) {
if ($newvalue === NULL) {
unset($this->value[$key]);
} else {
$value['role'] = $newvalue;
}
} elseif (($source[0] == 'user' || $source[0] == 'group') && (($member_key = array_search($oldvalue, $value['members'])) !== FALSE)) {
} elseif (($source['CLASS'] == 'user' || $source['CLASS'] == 'group') && (($member_key = array_search($oldvalue, $value['members'])) !== FALSE)) {
if ($newvalue === NULL) {
unset($value['members'][$member_key]);
} else {
$value['members'][$member_key] = $newvalue;
}
} elseif (!in_array($source[0], array('aclRole','user','group'))) {
trigger_error('unknown source '.$source[0]);
} elseif (!in_array($source['CLASS'], array('aclRole','user','group'))) {
trigger_error('unknown source '.$source['CLASS']);
}
}
unset($value);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment