src/Security/CostVoter.php line 115

Open in your IDE?
  1. <?php
  2. //------------------------------------------------------------------------------
  3. // src/Security/CostVoter.php
  4. //------------------------------------------------------------------------------
  5. namespace App\Security;
  6. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  7. use Symfony\Component\Security\Core\Authorization\Voter\Voter;
  8. use Doctrine\Persistence\ManagerRegistry;
  9. use App\Entity\Access;
  10. use App\Entity\Config\Config;
  11. use App\Entity\Config\Module;
  12. use App\Entity\HR\AccessFunction;
  13. use App\Entity\Platform\Cost\Cost;
  14. use App\Entity\Platform\Cost\CostNote;
  15. use App\Entity\Security\Acl;
  16. use App\Entity\Security\AclPermission;
  17. use App\Services\LogTools;
  18. use App\Services\Config\OptionConfigTools;
  19. use App\Services\Config\ModuleTools;
  20. class CostVoter extends Voter
  21. {
  22.     //--------------------------------------------------------------------------------
  23.     // is_granted constants
  24.     const IS_ACTIVE "cost_is_active";
  25.     const ADD "add_cost";
  26.     const ADD_FOR_OTHERS "add_cost_for_others";
  27.     const ADD_WITH_EDITABLE_STATUS "add_cost_with_editable_status";
  28.     // Plan.io Task #4507
  29.     const ADD_COST_VENDOR_INVOICE "add_cost_vendor_invoice";
  30.     const LISTING "list_costs";
  31.     const LISTING_SOCIETY "list_costs_society";
  32.     const LISTING_OWN "list_costs_own";
  33.     const LISTING_ANY "list_costs_any";
  34.     const VIEW "view_cost";
  35.     const EDIT "edit_cost";
  36.     const EDIT_STATUS "edit_cost_status";
  37.     const EDIT_TYPE "edit_cost_type";
  38.     const DELETE "delete_cost";
  39.     const SEEN "mark_seen_cost";
  40.     const ADD_COST_NOTE "add_cost_note";
  41.     const EDIT_COST_NOTE "edit_cost_note";
  42.     const DELETE_COST_NOTE "delete_cost_note";
  43.     // Plan.io Task #4426
  44.     const IS_ACTIVE_COST_AUTO_ACCOUNT "cost_auto_account_is_active";
  45.     const IS_GRANTED_CONSTANTS = array(
  46.         self::IS_ACTIVE,
  47.         self::ADD,
  48.         self::ADD_FOR_OTHERS,
  49.         self::ADD_WITH_EDITABLE_STATUS,
  50.         self::ADD_COST_VENDOR_INVOICE,
  51.         self::LISTING,
  52.         self::LISTING_SOCIETY,
  53.         self::LISTING_OWN,
  54.         self::LISTING_ANY,
  55.         self::VIEW,
  56.         self::EDIT,
  57.         self::EDIT_STATUS,
  58.         self::EDIT_TYPE,
  59.         self::DELETE,
  60.         self::SEEN,
  61.         self::ADD_COST_NOTE,
  62.         self::EDIT_COST_NOTE,
  63.         self::DELETE_COST_NOTE,
  64.         self::IS_ACTIVE_COST_AUTO_ACCOUNT,
  65.     );
  66.     //--------------------------------------------------------------------------------
  67.     // acl constants
  68.     const ACL_PERM_ADD "cost_add";
  69.     const ACL_PERM_ADD_FOR_OTHERS "cost_add_for_others";
  70.     const ACL_PERM_ADD_WITH_EDITABLE_STATUS "cost_add_with_editable_status";
  71.     
  72.     // Plan.io Task #4507
  73.     const ACL_PERM_ADD_VENDOR_INVOICE "cost_vendor_invoice_add";
  74.     
  75.     const ACL_PERM_LISTING "cost_list";
  76.     const ACL_PERM_LISTING_SOCIETY "cost_list_society";
  77.     const ACL_PERM_LISTING_OWN "cost_list_own";
  78.     const ACL_PERM_VIEW "cost_view";
  79.     const ACL_PERM_VIEW_SOCIETY "cost_view_society";
  80.     const ACL_PERM_VIEW_OWN "cost_view_own";
  81.     const ACL_PERM_EDIT "cost_edit";
  82.     const ACL_PERM_EDIT_SOCIETY "cost_edit_society";
  83.     const ACL_PERM_EDIT_OWN "cost_edit_own";
  84.     const ACL_PERM_EDIT_STATUS "cost_edit_status";
  85.     const ACL_PERM_EDIT_STATUS_SOCIETY "cost_edit_status_society";
  86.     const ACL_PERM_DELETE "cost_delete";
  87.     const ACL_PERM_DELETE_SOCIETY "cost_delete_society";
  88.     const ACL_PERM_DELETE_OWN "cost_delete_own";
  89.     const ACL_PERM_SEEN "cost_seen";
  90.     //--------------------------------------------------------------------------------
  91.     public function __construct(ManagerRegistry $doctrineModuleTools $moduleToolsOptionConfigTools $optionConfigToolsLogTools $logTools)
  92.     {
  93.         $this->em $doctrine->getManager();
  94.         $this->optionConfigTools $optionConfigTools;
  95.         $this->moduleTools $moduleTools;
  96.         $this->logTools $logTools;
  97.         $this->aclRepository $this->em->getRepository(Acl::class);
  98.         $this->aclPermissionRepository $this->em->getRepository(AclPermission::class);
  99.     }
  100.     // Plan.io Task #4453 [See AccessVoter for details]
  101.     public function supportsAttribute(string $attribute): bool
  102.     {
  103.         return in_array($attributeself::IS_GRANTED_CONSTANTStrue);
  104.     }
  105.     
  106.     protected function supports(string $attribute$subject null): bool
  107.     {
  108.         // if the attribute isn't one we support, return false
  109.         if (!in_array($attributeself::IS_GRANTED_CONSTANTS))
  110.         {
  111.             return false;
  112.         }
  113.         // only vote on Cost objects inside this voter
  114.         if ($subject !== null && (!$subject instanceof Cost && !$subject instanceof CostNote))
  115.         {
  116.             return false;
  117.         }
  118.         return true;
  119.     }
  120.     protected function voteOnAttribute(string $attribute$subjectTokenInterface $token): bool
  121.     {
  122.         $user $token->getUser();
  123.         if (!$user instanceof Access)
  124.         {
  125.             // the user must be logged in; if not, deny access
  126.             return false;
  127.         }
  128.         // The user must have a function; if not deny access
  129.         $function $user->getFunction();
  130.         if ($function === null)        return false;
  131.         // Plan.io Task #3710 : Get current group
  132.         $currentGroup $user->getSocietyGroup();
  133.         if ($currentGroup === null)
  134.             return false;
  135.         // Module activated ?
  136.         if ($this->moduleTools->isInactiveByCode($currentGroupModule::MODULE_COST))
  137.         {
  138.             return false;
  139.         }
  140.         // you know $subject is a Cost/CostNote object, thanks to supports
  141.         $costNote null;
  142.         if ($subject instanceof CostNote)
  143.         {
  144.             /** @var CostNote $costNote */
  145.             $costNote $subject;
  146.             /** @var Cost $cost */
  147.             $cost $costNote->getCost();
  148.         }
  149.         else
  150.         {
  151.             /** @var Cost $cost */
  152.             $cost $subject;
  153.         }
  154.         // Check current group affectation
  155.         if ($subject !== null)
  156.         {
  157.             $subjectSociety $subject->getSociety();
  158.             if ($subjectSociety === null)
  159.                 return false;
  160.             $subjectGroup $subjectSociety->getGroup();
  161.             if ($subjectGroup === null)
  162.                 return false;
  163.             if (!$currentGroup->equals($subjectGroup))
  164.                 return false;
  165.         }
  166.         switch ($attribute)
  167.         {
  168.             case self::IS_ACTIVE:
  169.                 return true;
  170.             case self::IS_ACTIVE_COST_AUTO_ACCOUNT:
  171.             {
  172.                 return $this->optionConfigTools->isActive_CostAutoAccount($currentGroup);
  173.             }
  174.             case self::ADD:
  175.                 return $this->canAdd($user$function);
  176.             case self::ADD_FOR_OTHERS:
  177.                 return $this->canAddForOthers($user$function);
  178.             case self::ADD_WITH_EDITABLE_STATUS:
  179.                 return $this->canAddWithEditableStatus($user$function);
  180.             
  181.             // Plan.io Task #4507
  182.             case self::ADD_COST_VENDOR_INVOICE:
  183.                 return $this->canAddVendorInvoice($user$function);
  184.             case self::LISTING:
  185.                 return $this->canList($user$function);
  186.             case self::LISTING_SOCIETY:
  187.                 return $this->canListSociety($user$function);
  188.             case self::LISTING_OWN:
  189.                 return $this->canListOwn($user$function);
  190.             case self::LISTING_ANY:
  191.                 return $this->canListAny($user$function);
  192.             case self::VIEW:
  193.                 return $this->canView($cost$user$function);
  194.             case self::EDIT:
  195.                 return $this->canEdit($cost$user$function);
  196.             case self::EDIT_STATUS:
  197.                 return $this->canEditStatus($cost$user$function);
  198.             case self::EDIT_TYPE:
  199.                 return $this->canEditType($cost$user$function);
  200.             case self::DELETE:
  201.                 return $this->canDelete($cost$user$function);
  202.             case self::SEEN:
  203.                 return $this->canMarkAsSeen($cost$user$function);
  204.             case self::ADD_COST_NOTE:
  205.                 return $this->canAddCostNote($cost$user$function);
  206.             case self::EDIT_COST_NOTE:
  207.                 return $this->canEditCostNote($costNote$user$function);
  208.             case self::DELETE_COST_NOTE:
  209.                 return $this->canDeleteCostNote($costNote$user$function);
  210.         }
  211.         throw new \LogicException('This code should not be reached!');
  212.     }
  213.     // $access is the user trying to load the resource
  214.     // $cost is the resource being loaded
  215.     // Check if the Society of the resource
  216.     // belongs to the societies of the $access
  217.     private function checkSociety(Cost $costAccess $access)
  218.     {
  219.         // Get all the societies of the access
  220.         $societies $access->getSocieties();
  221.         // Get the Society of the Cost
  222.         $costSociety $cost->getSociety();
  223.         if ($costSociety === null)
  224.             return false;
  225.         $found false;
  226.         foreach ($societies as $society)
  227.         {
  228.             if ($society->getId() == $costSociety->getId())
  229.             {
  230.                 $found true;
  231.                 break;
  232.             }
  233.         }
  234.         return $found;
  235.     }
  236.     // Check if the $access is the manager / author of the $cost
  237.     private function checkOwn(Cost $costAccess $access)
  238.     {
  239.         // Get author
  240.         $author $cost->getAuthor();
  241.         if ($author === null)
  242.             return false;
  243.         if ($author->getId() === $access->getId())
  244.             return true;
  245.         // Get access
  246.         $theOne $cost->getAccess();
  247.         if ($theOne === null)
  248.             return false;
  249.         if ($theOne->getId() === $access->getId())
  250.             return true;
  251.         return false;
  252.     }
  253.     private function canAdd(Access $userAccessFunction $function)
  254.     {
  255.         // Get Acl_Permission
  256.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_ADD);
  257.         if ($aclPerm === null)        return false;
  258.         // Get Acl
  259.         $acl $this->aclRepository->findOneBy(array(
  260.             'function'        =>    $function,
  261.             'permission'    =>    $aclPerm
  262.         ));
  263.         if ($acl === null)        return false;
  264.         // Since only one acl type can exist
  265.         // we can return the result of the acl_permission
  266.         return $acl->getValue();
  267.     }
  268.     public function canAddForOthers(Access $userAccessFunction $function)
  269.     {
  270.         // Get Acl_Permission
  271.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_ADD_FOR_OTHERS);
  272.         if ($aclPerm === null)        return false;
  273.         // Get Acl
  274.         $acl $this->aclRepository->findOneBy(array(
  275.             'function'        =>    $function,
  276.             'permission'    =>    $aclPerm
  277.         ));
  278.         if ($acl === null)        return false;
  279.         // Since only one acl type can exist
  280.         // we can return the result of the acl_permission
  281.         return $acl->getValue();
  282.     }
  283.     public function canAddWithEditableStatus(Access $userAccessFunction $function)
  284.     {
  285.         // Get Acl_Permission
  286.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_ADD_WITH_EDITABLE_STATUS);
  287.         if ($aclPerm === null)        return false;
  288.         // Get Acl
  289.         $acl $this->aclRepository->findOneBy(array(
  290.             'function'        =>    $function,
  291.             'permission'    =>    $aclPerm
  292.         ));
  293.         if ($acl === null)        return false;
  294.         // Since only one acl type can exist
  295.         // we can return the result of the acl_permission
  296.         return $acl->getValue();
  297.     }
  298.     // Plan.io Task #4507
  299.     public function canAddVendorInvoice(Access $userAccessFunction $function)
  300.     {
  301.         // Get Acl_Permission
  302.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_ADD_VENDOR_INVOICE);
  303.         if ($aclPerm === null)        return false;
  304.         // Get Acl
  305.         $acl $this->aclRepository->findOneBy(array(
  306.             'function'        =>    $function,
  307.             'permission'    =>    $aclPerm
  308.         ));
  309.         if ($acl === null)        return false;
  310.         // Since only one acl type can exist
  311.         // we can return the result of the acl_permission
  312.         return $acl->getValue();
  313.     }
  314.     private function canList(Access $userAccessFunction $function)
  315.     {
  316.         // Get Acl_Permission
  317.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LISTING);
  318.         if ($aclPerm === null)        return false;
  319.         // Get Acl
  320.         $acl $this->aclRepository->findOneBy(array(
  321.             'function'        =>    $function,
  322.             'permission'    =>    $aclPerm
  323.         ));
  324.         if ($acl === null)        return false;
  325.         // Since only one acl type can exist
  326.         // we can return the result of the acl_permission
  327.         return $acl->getValue();
  328.     }
  329.     private function canListSociety(Access $userAccessFunction $function)
  330.     {
  331.         // Get Acl_Permission
  332.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LISTING_SOCIETY);
  333.         if ($aclPerm === null)        return false;
  334.         // Get Acl
  335.         $acl $this->aclRepository->findOneBy(array(
  336.             'function'        =>    $function,
  337.             'permission'    =>    $aclPerm
  338.         ));
  339.         if ($acl === null)        return false;
  340.         // Since only one acl type can exist
  341.         // we can return the result of the acl_permission
  342.         // Further filtering is done in the Controller
  343.         return $acl->getValue();
  344.     }
  345.     private function canListOwn(Access $userAccessFunction $function)
  346.     {
  347.         // Get Acl_Permission
  348.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LISTING_OWN);
  349.         if ($aclPerm === null)        return false;
  350.         // Get Acl
  351.         $acl $this->aclRepository->findOneBy(array(
  352.             'function'        =>    $function,
  353.             'permission'    =>    $aclPerm
  354.         ));
  355.         if ($acl === null)        return false;
  356.         // Since only one acl type can exist
  357.         // we can return the result of the acl_permission
  358.         // Further filtering is done in the Controller
  359.         return $acl->getValue();
  360.     }
  361.     private function canListAny(Access $userAccessFunction $function)
  362.     {
  363.         // Two Acl_Permission may exist
  364.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LISTING);
  365.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LISTING_SOCIETY);
  366.         $aclPermOwn $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LISTING_OWN);
  367.         // If all are null, exit
  368.         if ($aclPerm === null && $aclPermSociety === null && $aclPermOwn === null)
  369.             return false;
  370.         // Get First one
  371.         if ($aclPerm !== null)
  372.         {
  373.             $acl $this->aclRepository->findOneBy(array(
  374.                 'function'        =>    $function,
  375.                 'permission'    =>    $aclPerm
  376.             ));
  377.             if ($acl !== null)
  378.             {
  379.                 if ($acl->getValue())
  380.                 {
  381.                     // A single positive answer is enough
  382.                     return true;
  383.                 }
  384.             }
  385.         }
  386.         // If we are here it means that nothing good has been found
  387.         // Load second permission
  388.         if ($aclPermSociety !== null)
  389.         {
  390.             $acl $this->aclRepository->findOneBy(array(
  391.                 'function'        =>    $function,
  392.                 'permission'    =>    $aclPermSociety
  393.             ));
  394.             if ($acl !== null)
  395.             {
  396.                 if ($acl->getValue())
  397.                 {
  398.                     // A single positive answer is enough
  399.                     return true;
  400.                 }
  401.             }
  402.         }
  403.         // If we are here it means that nothing good has been found
  404.         // Load third permission
  405.         if ($aclPermOwn !== null)
  406.         {
  407.             $acl $this->aclRepository->findOneBy(array(
  408.                 'function'        =>    $function,
  409.                 'permission'    =>    $aclPermOwn
  410.             ));
  411.             if ($acl !== null)
  412.             {
  413.                 if ($acl->getValue())
  414.                 {
  415.                     // A single positive answer is enough
  416.                     return true;
  417.                 }
  418.             }
  419.         }
  420.         // If we are here, all hope is lost
  421.         return false;
  422.     }
  423.     private function canView(Cost $costAccess $userAccessFunction $function)
  424.     {
  425.         // Get Acl_Permissions
  426.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_VIEW);
  427.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_VIEW_SOCIETY);
  428.         $aclPermOwn $this->aclPermissionRepository->findOneByName(self::ACL_PERM_VIEW_OWN);
  429.         // If all are null, exit
  430.         if ($aclPerm === null && $aclPermSociety === null && $aclPermOwn === null)
  431.             return false;
  432.         // Get First one
  433.         if ($aclPerm !== null)
  434.         {
  435.             $acl $this->aclRepository->findOneBy(array(
  436.                 'function'        =>    $function,
  437.                 'permission'    =>    $aclPerm
  438.             ));
  439.             if ($acl !== null)
  440.             {
  441.                 if ($acl->getValue())
  442.                 {
  443.                     // A single positive answer is enough
  444.                     return true;
  445.                 }
  446.             }
  447.         }
  448.         // If we are here it means that nothing good has been found
  449.         // Load second permission
  450.         if ($aclPermSociety !== null)
  451.         {
  452.             $acl $this->aclRepository->findOneBy(array(
  453.                 'function'        =>    $function,
  454.                 'permission'    =>    $aclPermSociety
  455.             ));
  456.             if ($acl !== null)
  457.             {
  458.                 if ($acl->getValue())
  459.                 {
  460.                     // A single positive answer is enough
  461.                     // In this case the good answer will be provided by the checkSociety
  462.                     return $this->checkSociety($cost$user);
  463.                 }
  464.             }
  465.         }
  466.         // If we are here it means that nothing good has been found
  467.         // Load third permission
  468.         if ($aclPermOwn !== null)
  469.         {
  470.             $acl $this->aclRepository->findOneBy(array(
  471.                 'function'        =>    $function,
  472.                 'permission'    =>    $aclPermOwn
  473.             ));
  474.             if ($acl !== null)
  475.             {
  476.                 if ($acl->getValue())
  477.                 {
  478.                     // A single positive answer is enough
  479.                     // In this case the good answer will be provided by the checkOwn
  480.                     return $this->checkOwn($cost$user);
  481.                 }
  482.             }
  483.         }
  484.         // If we are here, all hope is lost
  485.         return false;
  486.     }
  487.     private function canEdit(Cost $costAccess $userAccessFunction $function)
  488.     {
  489.         // Children only
  490.         // Plan.io Task #4416 => VendorInvoice also
  491.         if ($cost->getParent() === null && $cost->isNotVendorInvoice())
  492.         {
  493.             return false;
  494.         }
  495.         // If the initial status has changed => Deny editing
  496.         if ($cost->getStatus() === null)
  497.         {
  498.             // This should not happen
  499.             return false;
  500.         }
  501.         else
  502.         {
  503.             if ($cost->getStatus()->isNotDefaultValue())
  504.             {
  505.                 return false;
  506.             }
  507.         }
  508.         // Three Acl_Permission may exist
  509.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT);
  510.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT_SOCIETY);
  511.         $aclPermOwn $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT_OWN);
  512.         // If all are null, exit
  513.         if ($aclPerm === null && $aclPermSociety === null && $aclPermOwn === null)
  514.             return false;
  515.         // Get First one
  516.         if ($aclPerm !== null)
  517.         {
  518.             $acl $this->aclRepository->findOneBy(array(
  519.                 'function'        =>    $function,
  520.                 'permission'    =>    $aclPerm
  521.             ));
  522.             if ($acl !== null)
  523.             {
  524.                 if ($acl->getValue())
  525.                 {
  526.                     // A single positive answer is enough
  527.                     return true;
  528.                 }
  529.             }
  530.         }
  531.         // If we are here it means that nothing good has been found
  532.         // Load second permission
  533.         if ($aclPermSociety !== null)
  534.         {
  535.             $acl $this->aclRepository->findOneBy(array(
  536.                 'function'        =>    $function,
  537.                 'permission'    =>    $aclPermSociety
  538.             ));
  539.             if ($acl !== null)
  540.             {
  541.                 if ($acl->getValue())
  542.                 {
  543.                     // A single positive answer is enough
  544.                     // In this case the good answer will be provided by the checkSociety
  545.                     return $this->checkSociety($cost$user);
  546.                 }
  547.             }
  548.         }
  549.         // If we are here it means that nothing good has been found
  550.         // Load third permission
  551.         if ($aclPermOwn !== null)
  552.         {
  553.             $acl $this->aclRepository->findOneBy(array(
  554.                 'function'        =>    $function,
  555.                 'permission'    =>    $aclPermOwn
  556.             ));
  557.             if ($acl !== null)
  558.             {
  559.                 if ($acl->getValue())
  560.                 {
  561.                     // A single positive answer is enough
  562.                     // In this case the good answer will be provided by the checkOwn
  563.                     return $this->checkOwn($cost$user);
  564.                 }
  565.             }
  566.         }
  567.         // If we are here, all hope is lost
  568.         return false;
  569.     }
  570.     private function canEditStatus(Cost $costAccess $userAccessFunction $function)
  571.     {
  572.         // Parent only
  573.         if (!$cost->isParent())
  574.         {
  575.             return false;
  576.         }
  577.         // Two Acl_Permission may exist
  578.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT_STATUS);
  579.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT_STATUS_SOCIETY);
  580.         // If all are null, exit
  581.         if ($aclPerm === null && $aclPermSociety === null)
  582.             return false;
  583.         // Get First one
  584.         if ($aclPerm !== null)
  585.         {
  586.             $acl $this->aclRepository->findOneBy(array(
  587.                 'function'        =>    $function,
  588.                 'permission'    =>    $aclPerm
  589.             ));
  590.             if ($acl !== null)
  591.             {
  592.                 if ($acl->getValue())
  593.                 {
  594.                     // A single positive answer is enough
  595.                     return true;
  596.                 }
  597.             }
  598.         }
  599.         // If we are here it means that nothing good has been found
  600.         // Load second permission
  601.         if ($aclPermSociety !== null)
  602.         {
  603.             $acl $this->aclRepository->findOneBy(array(
  604.                 'function'        =>    $function,
  605.                 'permission'    =>    $aclPermSociety
  606.             ));
  607.             if ($acl !== null)
  608.             {
  609.                 if ($acl->getValue())
  610.                 {
  611.                     // A single positive answer is enough
  612.                     // In this case the good answer will be provided by the checkSociety
  613.                     return $this->checkSociety($cost$user);
  614.                 }
  615.             }
  616.         }
  617.         // If we are here, all hope is lost
  618.         return false;
  619.     }
  620.     public function canEditType(Cost $costAccess $userAccessFunction $function)
  621.     {
  622.         // Parents only
  623.         if ($cost->getParent() !== null)
  624.         {
  625.             return false;
  626.         }
  627.         // No Acl_Permissions for now (Same as Rekto version)
  628.         if ($cost->getStatus() === null)
  629.         {
  630.             return false;
  631.         }
  632.         if ($cost->getStatus()->isDefaultValue())
  633.         {
  634.             return true;
  635.         }
  636.         // If we are here, all hope is lost
  637.         return false;
  638.     }
  639.     public function canDelete(Cost $costAccess $userAccessFunction $function)
  640.     {
  641.         // Children only
  642.         // Plan.io Task #4416 => VendorInvoice also
  643.         if ($cost->getParent() === null && $cost->isNotVendorInvoice())
  644.         {
  645.             return false;
  646.         }
  647.         // Check status (children only => avoid error when dealing with VendorInvoice Costs)
  648.         if ($cost->getParent() !== null)
  649.         {
  650.             if ($cost->getParent()->getStatus() === null)
  651.             {
  652.                 // This should not happen
  653.                 return false;
  654.             }
  655.             if ($cost->getParent()->getStatus()->deniesDelete())
  656.             {
  657.                 return false;
  658.             }
  659.         }
  660.         else
  661.         {
  662.             // Parent is null, so this is a Cost VendorInvoice
  663.             // => Check status directly
  664.             if ($cost->getStatus()->deniesDelete())
  665.             {
  666.                 return false;
  667.             }
  668.         }
  669.         // Three Acl_Permission may exist
  670.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_DELETE);
  671.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_DELETE_SOCIETY);
  672.         $aclPermOwn $this->aclPermissionRepository->findOneByName(self::ACL_PERM_DELETE_OWN);
  673.         // If all are null, exit
  674.         if ($aclPerm === null && $aclPermSociety === null && $aclPermOwn === null)
  675.             return false;
  676.         // Get First one
  677.         if ($aclPerm !== null)
  678.         {
  679.             $acl $this->aclRepository->findOneBy(array(
  680.                 'function'        =>    $function,
  681.                 'permission'    =>    $aclPerm
  682.             ));
  683.             if ($acl !== null)
  684.             {
  685.                 if ($acl->getValue())
  686.                 {
  687.                     // A single positive answer is enough
  688.                     return true;
  689.                 }
  690.             }
  691.         }
  692.         // If we are here it means that nothing good has been found
  693.         // Load second permission
  694.         if ($aclPermSociety !== null)
  695.         {
  696.             $acl $this->aclRepository->findOneBy(array(
  697.                 'function'        =>    $function,
  698.                 'permission'    =>    $aclPermSociety
  699.             ));
  700.             if ($acl !== null)
  701.             {
  702.                 if ($acl->getValue())
  703.                 {
  704.                     // A single positive answer is enough
  705.                     // In this case the good answer will be provided by the checkSociety
  706.                     return $this->checkSociety($cost$user);
  707.                 }
  708.             }
  709.         }
  710.         // If we are here it means that nothing good has been found
  711.         // Load third permission
  712.         if ($aclPermOwn !== null)
  713.         {
  714.             $acl $this->aclRepository->findOneBy(array(
  715.                 'function'        =>    $function,
  716.                 'permission'    =>    $aclPermOwn
  717.             ));
  718.             if ($acl !== null)
  719.             {
  720.                 if ($acl->getValue())
  721.                 {
  722.                     // A single positive answer is enough
  723.                     // In this case the good answer will be provided by the checkOwn
  724.                     return $this->checkOwn($cost$user);
  725.                 }
  726.             }
  727.         }
  728.         // If we are here, all hope is lost
  729.         return false;
  730.     }
  731.     public function canMarkAsSeen(Cost $costAccess $userAccessFunction $function)
  732.     {
  733.         // Children only
  734.         if ($cost->getParent() === null)
  735.         {
  736.             return false;
  737.         }
  738.         // Get Acl_Permission
  739.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_SEEN);
  740.         if ($aclPerm === null)        return false;
  741.         // Get Acl
  742.         $acl $this->aclRepository->findOneBy(array(
  743.             'function'        =>    $function,
  744.             'permission'    =>    $aclPerm
  745.         ));
  746.         if ($acl === null)        return false;
  747.         // Since only one acl type can exist
  748.         // we can return the result of the acl_permission
  749.         return $acl->getValue();
  750.     }
  751.     public function canAddCostNote(Cost $costAccess $userAccessFunction $function)
  752.     {
  753.         // Only parent case
  754.         if ($cost->isChild())
  755.         {
  756.             return false;
  757.         }
  758.         // In all cases (Plan.io Task #3001)
  759.         return true;
  760.     }
  761.     public function canEditCostNote(CostNote $costNoteAccess $userAccessFunction $function)
  762.     {
  763.         if ($costNote->getCost() === null || $costNote->getAuthor() === null)
  764.         {
  765.             // Should never happen
  766.             return false;
  767.         }
  768.         // Author case
  769.         if ($costNote->getAuthor()->equals($user))
  770.         {
  771.             return true;
  772.         }
  773.         // In all cases (Plan.io Task #3001)
  774.         return true;
  775.     }
  776.     public function canDeleteCostNote(CostNote $costNoteAccess $userAccessFunction $function)
  777.     {
  778.         if ($costNote->getCost() === null || $costNote->getAuthor() === null)
  779.         {
  780.             // Should never happen
  781.             return false;
  782.         }
  783.         // Author case
  784.         if ($costNote->getAuthor()->equals($user))
  785.         {
  786.             return true;
  787.         }
  788.         // In all cases (Plan.io Task #3001)
  789.         return true;
  790.     }
  791. }