/**
  * Creates an ability and links it to a given competency.
  *
  * @param Competency    $parent
  * @param Ability       $ability
  * @param Level         $level
  * @return \HeVinci\CompetencyBundle\Entity\Ability
  * @throws \LogicException if the parent competency is not a leaf node
  */
 public function createAbility(Competency $parent, Ability $ability, Level $level)
 {
     if ($parent->getRight() - $parent->getLeft() > 1) {
         throw new \LogicException("Cannot associate an ability with competency '{$parent->getName()}'" . ': competency must be a leaf node');
     }
     $link = new CompetencyAbility();
     $link->setCompetency($parent);
     $link->setAbility($ability);
     $link->setLevel($level);
     $this->om->persist($ability);
     $this->om->persist($link);
     $this->om->flush();
     return $ability;
 }
 /**
  * Returns an array representation of activity evaluation data for
  * a given user and a given competency, including information about
  * the activity and the related abilities.
  *
  * @param Competency $competency
  * @param User       $user
  *
  * @return array
  *
  * @throws \Exception
  */
 public function findEvaluationsByCompetency(Competency $competency, User $user)
 {
     if ($competency->getRight() - $competency->getLeft() > 1) {
         throw new \Exception('Expected leaf competency');
     }
     $activityQb = $this->createQueryBuilder('a1')->select('ac1.id')->join('a1.activities', 'ac1')->join('a1.competencyAbilities', 'ca')->where('ca.competency = :competency');
     return $this->_em->createQueryBuilder()->select('e.id AS evaluationId', 'e.status', 'e.date', 'ac.id AS activityId', 'n.name AS activityName', 'a.id AS abilityId', 'a.name AS abilityName', 'l.name AS levelName')->from('Claroline\\CoreBundle\\Entity\\Activity\\Evaluation', 'e')->join('e.user', 'u')->join('e.activityParameters', 'ap')->join('ap.activity', 'ac')->join('ac.resourceNode', 'n')->join('HeVinci\\CompetencyBundle\\Entity\\Ability', 'a', 'WITH', 'ac IN (SELECT ac2 FROM HeVinci\\CompetencyBundle\\Entity\\Ability a2 JOIN a2.activities ac2 WHERE a2 = a)')->join('a.competencyAbilities', 'ca2')->join('ca2.level', 'l')->join('ca2.competency', 'c2')->where('c2 = :competency')->where($activityQb->expr()->in('ac', $activityQb->getQuery()->getDQL()))->andWhere('u = :user')->orderBy('e.date, e.id, a.id', 'ASC')->setParameters([':competency' => $competency, ':user' => $user])->getQuery()->getArrayResult();
 }
 private function getSiblingNodes(Competency $startNode, Competency $parent, array $related)
 {
     return array_filter($related, function ($node) use($startNode, $parent) {
         return $node !== $startNode && $node->getLevel() === $startNode->getLevel() && $node->getLeft() > $parent->getLeft() && $node->getRight() < $parent->getRight();
     });
 }