/**
  * Returns the association between a competency and an ability.
  *
  * @param Competency $parent
  * @param Ability    $ability
  *
  * @return null|object
  *
  * @throws \Exception if the ability is not linked to the competency
  */
 public function findOneByTerms(Competency $parent, Ability $ability)
 {
     $link = $this->findOneBy(['competency' => $parent, 'ability' => $ability]);
     if (!$link) {
         throw new \RuntimeException("Competency {$parent->getId()} is not linked to ability {$ability->getId()}");
     }
     return $link;
 }
 private function loadAbility(Ability $ability)
 {
     return ['id' => $ability->getId(), 'name' => $ability->getName(), 'type' => 'ability_', 'paths' => array_map(function ($link) {
         return ['level' => $link->getLevel()->getName(), 'steps' => array_map(function ($step) {
             return $step->getName();
         }, $this->competencyRepo->getPath($link->getCompetency()))];
     }, $ability->getCompetencyAbilities()->toArray())];
 }
 /**
  * Creates a link between a competency and an existing ability.
  *
  * @param Competency $parent
  * @param Ability $ability
  * @param Level $level
  * @return Ability
  * @throws \LogicException if a link already exists
  */
 public function linkAbilityToCompetency(Competency $parent, Ability $ability, Level $level)
 {
     $link = $this->competencyAbilityRepo->findOneBy(['competency' => $parent, 'ability' => $ability]);
     if ($link) {
         throw new \LogicException("Ability {$ability->getId()} is already linked to competency {$parent->getId()}");
     }
     $link = new CompetencyAbility();
     $link->setCompetency($parent);
     $link->setAbility($ability);
     $link->setLevel($level);
     $this->om->persist($link);
     $this->om->flush();
     return $ability;
 }