/**
  * Adds a tag to a problem
  *
  * @param Request $r
  * @return array
  * @throws InvalidDatabaseOperationException
  * @throws ForbiddenAccessException
  */
 public static function apiAddTag(Request $r)
 {
     // Check problem_alias
     Validators::isStringNonEmpty($r['problem_alias'], 'problem_alias');
     // Authenticate logged user
     self::authenticateRequest($r);
     $problem = ProblemsDAO::getByAlias($r['problem_alias']);
     if (!Authorization::IsProblemAdmin($r['current_user_id'], $problem)) {
         throw new ForbiddenAccessException();
     }
     // Normalize name.
     $tag_name = $r['name'];
     Validators::isStringNonEmpty($tag_name, 'name');
     $tag_name = TagController::normalize($tag_name);
     try {
         $tag = TagsDAO::getByName($tag_name);
     } catch (Exception $e) {
         $this->log->info($e);
         // Operation failed in the data layer
         throw new InvalidDatabaseOperationException($e);
     }
     if ($tag == null) {
         try {
             $tag = new Tags();
             $tag->name = $tag_name;
             TagsDAO::save($tag);
         } catch (Exception $inner) {
             $this->log->info($e);
             // Operation failed in the data layer
             throw new InvalidDatabaseOperationException($inner);
         }
     }
     if (is_null($tag->tag_id)) {
         throw new InvalidDatabaseOperationException(new Exception('tag'));
     }
     $problem_tag = new ProblemsTags();
     $problem_tag->problem_id = $problem->problem_id;
     $problem_tag->tag_id = $tag->tag_id;
     $problem_tag->public = $r['public'] ? 1 : 0;
     // Save the tag to the DB
     try {
         ProblemsTagsDAO::save($problem_tag);
     } catch (Exception $e) {
         // Operation failed in the data layer
         self::$log->error('Failed to save tag', $e);
         throw new InvalidDatabaseOperationException($e);
     }
     return array('status' => 'ok', 'name' => $tag_name);
 }