/** * Copy Categories by Path (recursive copy). * * @param string $apath The path to copy from. * @param integer $newparent_id The categoryID of the new parent category. * @param string $field The field to use for the path reference (optional) (default='ipath'). * @param boolean $includeRoot Whether or not to also move the root folder (optional) (default=true). * * @return boolean */ public static function copyCategoriesByPath($apath, $newparent_id, $field = 'ipath', $includeRoot = true) { if (!$apath || !$newparent_id) { return false; } $cats = self::getSubCategoriesByPath($apath, 'ipath', $field, true, true); $newParentCats = self::getSubCategories($newparent_id, true, true, true, true, true); $newParent = $newParentCats[0]; if (!$newParent || !$cats) { return false; } $currentPaths = array(); foreach ($newParentCats as $p) { $currentPaths[] = $p['path_relative']; } // need to make sure that after copying categories will have unique paths foreach ($cats as $k => $cat) { if ($includeRoot) { // root node is included - just check path uniqueness for root // subnodes will inherit it's name in paths $catBasePath = $newParent['path_relative'] . '/'; if ($k === 0 && in_array($catBasePath . $cats[0]['name'], $currentPaths)) { // path is not unique - add arbitrary " Copy" suffix to category name $cats[0]['name'] .= ' ' . __('Copy'); if (in_array($catBasePath . $cats[0]['name'], $currentPaths)) { // if there is already such name // find first free name by adding number at the end $i = 1; $name = $cats[0]['name']; while (in_array($catBasePath . $name, $currentPaths)) { $name = $cats[0]['name'] . ' ' . $i++; } $cats[0]['name'] = $name; } } } elseif ($k !== 0) { // root node is excluded - need to check each subnode if it's path will be unique // follow the same routin that for the root node $catPath = explode('/', $cat['path_relative']); array_shift($catPath); array_pop($catPath); $catBasePath = $newParent['path_relative'] . '/' . implode('/', $catPath); if (in_array($catBasePath . $cats[$k]['name'], $currentPaths)) { $cats[$k]['name'] .= ' ' . __('Copy'); if (in_array($catBasePath . $cats[$k]['name'], $currentPaths)) { $i = 1; $name = $cats[$k]['name']; while (in_array($catBasePath . $name, $currentPaths)) { $name = $cats[$k]['name'] . ' ' . $i++; } $cats[$k]['name'] = $name; } } } } $em = ServiceUtil::get('doctrine.entitymanager'); $oldToNewID = array(); $oldToNewID[$cats[0]['parent']['id']] = $em->getReference('ZikulaCategoriesModule:CategoryEntity', $newParent['id']); // since array_shift() resets numeric array indexes, we remove the leading element like this if (!$includeRoot) { foreach ($cats as $k => $v) { if (isset($v['ipath']) && $v['ipath'] == $apath) { unset($cats[$k]); } } } $ak = array_keys($cats); foreach ($ak as $v) { $cat = $cats[$v]; // unset some variables unset($cat['parent_id']); unset($cat['accessible']); unset($cat['path_relative']); unset($cat['ipath_relative']); $oldID = $cat['id']; $cat['id'] = ''; $cat['parent'] = isset($oldToNewID[$cat['parent']['id']]) ? $oldToNewID[$cat['parent']['id']] : $em->getReference('ZikulaCategoriesModule:CategoryEntity', $newParent['id']); $catObj = new Zikula\Module\CategoriesModule\Entity\CategoryEntity(); $catObj->merge($cat); $em->persist($catObj); $em->flush(); $oldToNewID[$oldID] = $em->getReference('ZikulaCategoriesModule:CategoryEntity', $catObj['id']); } $em->flush(); // rebuild iPath since now we have all new PathIDs self::rebuildPaths('ipath', 'id'); // rebuild also paths since names could be changed self::rebuildPaths(); return true; }
/** * @Route("/save", options={"expose"=true}) * @Method("POST") * * Save a category * * @param Request $request * * @return AjaxResponse ajax response object */ public function saveAction(Request $request) { $this->checkAjaxToken(); $mode = $request->request->get('mode', 'new'); $accessLevel = $mode == 'edit' ? ACCESS_EDIT : ACCESS_ADD; if (!SecurityUtil::checkPermission('ZikulaCategoriesModule::', '::', $accessLevel)) { return new ForbiddenResponse($this->__('No permission for this action')); } // get data from post $data = $request->request->get('category', null); if (!isset($data['is_locked'])) { $data['is_locked'] = 0; } if (!isset($data['is_leaf'])) { $data['is_leaf'] = 0; } if (!isset($data['status'])) { $data['status'] = 'I'; } $valid = GenericUtil::validateCategoryData($data); if (!$valid) { $args = array('cid' => isset($data['cid']) ? $data['cid'] : 0, 'parent' => $data['parent_id'], 'mode' => $mode); return $this->editAction($args); } // process name $data['name'] = GenericUtil::processCategoryName($data['name']); // process parent $data['parent'] = GenericUtil::processCategoryParent($data['parent_id']); unset($data['parent_id']); // process display names $data['display_name'] = GenericUtil::processCategoryDisplayName($data['display_name'], $data['name']); // save category if ($mode == 'edit') { $category = $this->entityManager->find('ZikulaCategoriesModule:CategoryEntity', $data['id']); } else { $category = new \Zikula\Module\CategoriesModule\Entity\CategoryEntity(); } $prevCategoryName = $category['name']; $category->merge($data); $this->entityManager->persist($category); $this->entityManager->flush(); // process path and ipath $category['path'] = GenericUtil::processCategoryPath($data['parent']['path'], $category['name']); $category['ipath'] = GenericUtil::processCategoryIPath($data['parent']['ipath'], $category['id']); // process category attributes $attrib_names = $request->request->get('attribute_name', array()); $attrib_values = $request->request->get('attribute_value', array()); GenericUtil::processCategoryAttributes($category, $attrib_names, $attrib_values); $this->entityManager->flush(); // since a name change will change the object path, we must rebuild it here if ($prevCategoryName != $category['name']) { CategoryUtil::rebuildPaths('path', 'name', $category['id']); } $categories = CategoryUtil::getSubCategories($category['id'], true, true, true, true, true); $node = CategoryUtil::getJsTreeNodeFromCategoryArray(array(0 => $category)); $leafStatus = array('leaf' => array(), 'noleaf' => array()); foreach ($categories as $c) { if ($c['is_leaf']) { $leafStatus['leaf'][] = $c['id']; } else { $leafStatus['noleaf'][] = $c['id']; } } $result = array('action' => $mode == 'edit' ? 'edit' : 'add', 'cid' => $category['id'], 'parent' => $category['parent']->getId(), 'node' => $node, 'leafstatus' => $leafStatus, 'result' => true); return new AjaxResponse($result); }
/** * @Route("/edituser") * * edit categories for the currently logged in user * * @param Request $request * * @return Response a symfony reponse * * @throws AccessDeniedException Thrown if the user doesn't have edit permissions over categories in the module or * if the user is not logged in */ public function edituserAction(Request $request) { if (!SecurityUtil::checkPermission('ZikulaCategoriesModule::category', '::', ACCESS_EDIT)) { throw new AccessDeniedException(); } if (!UserUtil::isLoggedIn()) { throw new AccessDeniedException($this->__('Error! Editing mode for user-owned categories is only available to users who have logged-in.')); } $allowUserEdit = $this->getVar('allowusercatedit', 0); if (!$allowUserEdit) { $request->getSession()->getFlashBag()->add('error', $this->__('Error! User-owned category editing has not been enabled. This feature can be enabled by the site administrator.')); return $this->response($this->view->fetch('User/editcategories.tpl')); } $userRoot = $this->getVar('userrootcat', 0); if (!$userRoot) { $request->getSession()->getFlashBag()->add('error', $this->__('Error! Could not determine the user root node.')); return $this->response($this->view->fetch('User/editcategories.tpl')); } $userRootCat = CategoryUtil::getCategoryByPath($userRoot); if (!$userRoot) { $request->getSession()->getFlashBag()->add('error', $this->__f('Error! The user root node seems to point towards an invalid category: %s.', $userRoot)); return $this->response($this->view->fetch('User/editcategories.tpl')); } if ($userRootCat == 1) { $request->getSession()->getFlashBag()->add('error', $this->__("Error! The root directory cannot be modified in 'user' mode")); return $this->response($this->view->fetch('User/editcategories.tpl')); } $userCatName = $this->getusercategorynameAction(); if (!$userCatName) { $request->getSession()->getFlashBag()->add('error', $this->__('Error! Cannot determine user category root node name.')); return $this->response($this->view->fetch('User/editcategories.tpl')); } $thisUserRootCatPath = $userRoot . '/' . $userCatName; $thisUserRootCat = CategoryUtil::getCategoryByPath($thisUserRootCatPath); $dr = null; if (!$thisUserRootCat) { $autoCreate = $this->getVar('autocreateusercat', 0); if (!$autoCreate) { $request->getSession()->getFlashBag()->add('error', $this->__("Error! The user root category node for this user does not exist, and the automatic creation flag (autocreate) has not been set.")); return $this->response($this->view->fetch('User/editcategories.tpl')); } $cat = array('id' => '', 'parent' => $this->entityManager->getReference('ZikulaCategoriesModule:CategoryEntity', $userRootCat['id']), 'name' => $userCatName, 'display_name' => array(ZLanguage::getLanguageCode() => $userCatName), 'display_desc' => array(ZLanguage::getLanguageCode() => ''), 'path' => $thisUserRootCatPath, 'status' => 'A'); $obj = new \Zikula\Module\CategoriesModule\Entity\CategoryEntity(); $obj->merge($cat); $this->entityManager->persist($obj); $this->entityManager->flush(); // since the original insert can't construct the ipath (since // the insert id is not known yet) we update the object here $obj->setIPath($userRootCat['ipath'] . '/' . $obj['id']); $this->entityManager->flush(); $dr = $obj->getID(); $autoCreateDefaultUserCat = $this->getVar('autocreateuserdefaultcat', 0); if ($autoCreateDefaultUserCat) { $userdefaultcatname = $this->getVar('userdefaultcatname', $this->__('Default')); $cat = array('id' => '', 'parent' => $this->entityManager->getReference('ZikulaCategoriesModule:CategoryEntity', $dr), 'is_leaf' => 1, 'name' => $userdefaultcatname, 'sort_value' => 0, 'display_name' => array(ZLanguage::getLanguageCode() => $userdefaultcatname), 'display_desc' => array(ZLanguage::getLanguageCode() => ''), 'path' => $thisUserRootCatPath . '/' . $userdefaultcatname, 'status' => 'A'); $obj2 = new \Zikula\Module\CategoriesModule\Entity\CategoryEntity(); $obj2->merge($cat); $this->entityManager->persist($obj2); $this->entityManager->flush(); // since the original insert can't construct the ipath (since // the insert id is not known yet) we update the object here $obj2->setIPath($obj['ipath'] . '/' . $obj2['id']); $this->entityManager->flush(); } } else { $dr = $thisUserRootCat['id']; } return new RedirectResponse($this->get('router')->generate('zikulacategoriesmodule_user_edit', array('dr' => $dr), RouterInterface::ABSOLUTE_URL)); }
/** * @Route("/new") * @Method("POST") * * create category * * @param Request $request * * @return RedirectResponse * * @throws AccessDeniedException Thrown if the user doesn't have add permissions to the module * @throws \InvalidArgumentException Thrown if the document root is invalid */ public function newcatAction(Request $request) { $this->checkCsrfToken(); if (!SecurityUtil::checkPermission('ZikulaCategoriesModule::', '::', ACCESS_ADD)) { throw new AccessDeniedException(); } $dr = (int) $request->request->get('dr', 0); $url = $request->server->get('HTTP_REFERER'); if (!$dr) { throw new \InvalidArgumentException($this->__('Error! The document root is invalid.')); } // get data from post $data = $request->request->get('category', null); $valid = GenericUtil::validateCategoryData($data); if (!$valid) { return new RedirectResponse($this->get('router')->generate('zikulacategoriesmodule_user_edit', array('dr' => $dr), RouterInterface::ABSOLUTE_URL)); } // process name $data['name'] = GenericUtil::processCategoryName($data['name']); // process parent $data['parent'] = GenericUtil::processCategoryParent($data['parent_id']); unset($data['parent_id']); // process display names $data['display_name'] = GenericUtil::processCategoryDisplayName($data['display_name'], $data['name']); // process sort value $data['sort_value'] = 0; // save category $category = new \Zikula\Module\CategoriesModule\Entity\CategoryEntity(); $category->merge($data); $this->entityManager->persist($category); $this->entityManager->flush(); // process path and ipath $category['path'] = GenericUtil::processCategoryPath($data['parent']['path'], $category['name']); $category['ipath'] = GenericUtil::processCategoryIPath($data['parent']['ipath'], $category['id']); // process category attributes $attrib_names = $request->request->get('attribute_name', array()); $attrib_values = $request->request->get('attribute_value', array()); GenericUtil::processCategoryAttributes($category, $attrib_names, $attrib_values); $this->entityManager->flush(); $msg = $this->__f('Done! Inserted the %s category.', $data['name']); $request->getSession()->getFlashBag()->add('status', $msg); return new RedirectResponse(System::normalizeUrl($url)); }