wcmf logo wemove logo

class.AssociateController.php

Go to the documentation of this file.
00001 <?php
00002 /**
00003  * wCMF - wemove Content Management Framework
00004  * Copyright (C) 2005-2009 wemove digital solutions GmbH
00005  *
00006  * Licensed under the terms of any of the following licenses 
00007  * at your choice:
00008  *
00009  * - GNU Lesser General Public License (LGPL)
00010  *   http://www.gnu.org/licenses/lgpl.html
00011  * - Eclipse Public License (EPL)
00012  *   http://www.eclipse.org/org/documents/epl-v10.php
00013  *
00014  * See the license.txt file distributed with this work for 
00015  * additional information.
00016  *
00017  * $Id: class.AssociateController.php 950 2009-03-16 00:15:46Z iherwig $
00018  */
00019 require_once(BASE."wcmf/lib/presentation/class.Controller.php");
00020 require_once(BASE."wcmf/lib/persistence/class.PersistenceFacade.php");
00021 require_once(BASE."wcmf/lib/model/class.Node.php");
00022 require_once(BASE."wcmf/lib/model/class.NullNode.php");
00023 
00024 /**
00025  * @class AssociateController
00026  * @ingroup Controller
00027  * @brief AssociateController is a controller that (dis-)associates Nodes 
00028  * (by setting the parent/child relations).
00029  * 
00030  * <b>Input actions:</b>
00031  * - @em associate Associate one Node to another
00032  * - @em disassociate Disassociate one Node from another
00033  *
00034  * <b>Output actions:</b>
00035  * - @em ok In any case
00036  * 
00037  * @param[in] oid The object id of the Node to associate a Node as child to
00038  * @param[in] associateoids The object ids of the Nodes to (dis-)associate as parents/children (comma separated list)
00039  * @param[in] associateAs The role of the associated Nodes as seen from oid: Either 'parent' or 'child'
00040  *
00041  * @author      ingo herwig <ingo@wemove.com>
00042  */
00043 class AssociateController extends Controller
00044 {
00045   /**
00046    * @see Controller::validate()
00047    */
00048   function validate()
00049   {
00050     if(!PersistenceFacade::isValidOID($this->_request->getValue('oid')))
00051     {
00052       $this->setErrorMsg("No valid 'oid' given in data.");
00053       return false;
00054     }
00055     return true;
00056   }
00057   /**
00058    * @see Controller::hasView()
00059    */
00060   function hasView()
00061   {
00062     return false;
00063   }
00064   /**
00065    * (Dis-)Associate the Nodes.
00066    * @return Array of given context and action 'ok' in every case.
00067    * @see Controller::executeKernel()
00068    */
00069   function executeKernel()
00070   {
00071     $persistenceFacade = &PersistenceFacade::getInstance();    
00072     $lockManager = &LockManager::getInstance();
00073 
00074     // get parent node
00075     $parentOID = $this->_request->getValue('oid');
00076     $lockManager->releaseLock($parentOID);
00077     $parentNode = &$persistenceFacade->load($parentOID, BUILDDEPTH_SINGLE);
00078 
00079     // iterate over associateoids
00080     $associateoids = $this->_request->getValue('associateoids');
00081     $associateoidArray = split(',', $associateoids);
00082     foreach ($associateoidArray as $associateoid)
00083     {
00084       $associateoid = trim($associateoid);
00085       if(!PersistenceFacade::isValidOID($associateoid))
00086       {
00087         $this->setErrorMsg("Invalid oid given in data.");
00088         $this->_response->setAction('ok');
00089         return true;
00090       }
00091       
00092       // if the current user has a lock on the object, release it
00093       $lockManager->releaseLock($associateoid);
00094       $childNode = &$persistenceFacade->load($associateoid, BUILDDEPTH_SINGLE);
00095     
00096       if ($parentNode != null && $childNode != null)
00097       {
00098         // create templates of parent and child
00099         $parentType = PersistenceFacade::getOIDParameter($parentOID, 'type');
00100         $parentTemplate = &$persistenceFacade->create($parentType, 1);
00101         $childType = PersistenceFacade::getOIDParameter($associateoid, 'type');
00102         $childTemplate = &$persistenceFacade->create($childType, 1);
00103     
00104         // process actions
00105         if ($this->_request->getAction() == 'associate')
00106         {
00107           // check if we can directly associate child to parent
00108           if ($this->_request->getValue('associateAs') == 'child' && $this->isDirectAssociation($parentTemplate, $childTemplate))
00109           {
00110             $parentNode->addChild($childNode);
00111             $parentNode->setType($parentNode->getBaseType());
00112             $childNode->save();
00113           }
00114           // check if we can directly associate parent to child
00115           else if ($this->_request->getValue('associateAs') == 'parent' && $this->isDirectAssociation($childTemplate, $parentTemplate))
00116           {
00117             $childNode->addChild($parentNode);
00118             $parentNode->save();
00119           }
00120           else
00121           {
00122             // if the parent is connected via an association object, we have to create one
00123             $linkType = $this->findAssociationType($parentTemplate, $childTemplate);
00124             if ($linkType != null)
00125             {
00126               $link = &$persistenceFacade->create($linkType, BUILDTYPE_SINGLE);
00127               $parentNode->addChild($link);
00128               $link->save();
00129               $link = &$persistenceFacade->load($link->getOID(), BUILDTYPE_SINGLE);
00130               $childNode->addChild($link);
00131               $link->save();
00132             }
00133             else
00134             {
00135               $this->appendErrorMsg(Message::get("Cannot associate %1% and %2%. No direct connection and no connection type found.", 
00136                 array($associateoid, $parentOID)));
00137             }
00138           }
00139         }
00140         elseif ($this->_request->getAction() == 'disassociate')
00141         {
00142           // check if it is a direct association from child to parent
00143           if ($this->isDirectAssociation($parentTemplate, $childTemplate))
00144           {
00145             // use a NullNode to empty foreign key
00146             $parentNode = new NullNode($parentTemplate->getBaseType());
00147             $parentNode->addChild($childNode);
00148             $childNode->save();
00149           }
00150           // check if it is a direct association from parent to child
00151           else if ($this->isDirectAssociation($childTemplate, $parentTemplate))
00152           {
00153             // use a NullNode to empty foreign key
00154             $childNode = new NullNode($childTemplate->getType());
00155             $childNode->addChild($parentNode);
00156             $parentNode->save();
00157           }
00158           else
00159           {
00160             // if the parent is connected via an association object, we have to delete that
00161             $linkType = $this->findAssociationType($parentTemplate, $childTemplate);
00162             if ($linkType != null)
00163             {
00164               // find association object as child of both (parent and child)
00165               $parentLinks = $parentNode->getProperty('childoids');
00166               $childLinks = $childNode->getProperty('childoids');
00167               $linkOIDs = array_intersect($parentLinks, $childLinks);
00168               foreach($linkOIDs as $linkOID)
00169               {
00170                 if (PersistenceFacade::getOIDParameter($linkOID, 'type') == $linkType)
00171                 {
00172                   // load the object to trigger it's delete handler
00173                   $obj = &$persistenceFacade->load($linkOID, BUILDDEPTH_SINGLE);
00174                   $obj->delete();
00175                 }
00176               }
00177             }
00178             else
00179             {
00180               $this->appendErrorMsg(Message::get("Cannot disassociate %1% and %2%. No direct connection and no connection type found.", 
00181                 array($associateoid, $parentOID)));
00182             }
00183           }
00184         }
00185       }
00186     }
00187     $this->_response->setAction('ok');
00188     return true;
00189   }
00190 
00191   /**
00192    * Check if two Nodes are directly assiociated (in a direct parent-child relation)
00193    * @param parent A template of the parent object (with children attached)
00194    * @param child The child to check
00195    * @return True/False
00196    */
00197   function isDirectAssociation(&$parent, &$child)
00198   {
00199     $childTypeChildren = $parent->getChildrenEx(null, $child->getType(), null, null);
00200     if (sizeof($childTypeChildren) > 0)
00201       return true;
00202     else
00203       return false;
00204   }
00205 
00206   /**
00207    * Search for an child type of parent that establishes the association between a given
00208    * parent and child or vice versa.
00209    * @param parent A template of the parent object (with children attached)
00210    * @param child The child to check
00211    * @return The type
00212    */
00213   function findAssociationType(&$parent, &$child)
00214   {
00215     foreach ($parent->getChildren() as $possibleChild)
00216     {
00217       if (in_array('manyToMany', $possibleChild->getPropertyNames()))
00218       {
00219         $associationEnds = $possibleChild->getProperty('manyToMany');
00220         if (in_array($child->getType(), $associationEnds))
00221           return $possibleChild->getType();
00222       }
00223     }
00224     foreach ($child->getChildren() as $possibleChild)
00225     {
00226       if (in_array('manyToMany', $possibleChild->getPropertyNames()))
00227       {
00228         $associationEnds = $possibleChild->getProperty('manyToMany');
00229         if (in_array($parent->getType(), $associationEnds))
00230           return $possibleChild->getType();
00231       }
00232     }
00233     return null;
00234   }
00235 }
00236 ?>
00237 

This page generated via doxygen 1.5.8 Mon Mar 30 01:58:34 2009.
Copyright © 2009 wemove digital solutions GmbH.
sourceforge logo