public function testParseManga()
 {
     $mangaContents = file_get_contents(__DIR__ . '/../InputSamples/manga-upcoming.html');
     $upcomingList = Upcoming::parse($mangaContents, 'manga');
     $this->assertInternalType('array', $upcomingList);
     $upcomingItem = $upcomingList[0];
     $this->assertInstanceOf('Atarashii\\APIBundle\\Model\\Manga', $upcomingItem);
     /* Although this test is against a static downloaded copy, the values are likely to change considerably
      * each time the source file is updated. As such, mostly check the type and confirm a few things that
      * shouldn't change.
      */
     //Do some basic type checking for things that should exist (not null)
     $this->assertInternalType('int', $upcomingItem->getId());
     $this->assertInternalType('string', $upcomingItem->getTitle());
     $this->assertInternalType('string', $upcomingItem->getImageUrl());
     $this->assertInternalType('string', $upcomingItem->getType());
     $this->assertInternalType('string', $upcomingItem->getSynopsis());
     //Check some data that should remain consistent
     $this->assertStringStartsWith('https://myanimelist.cdn-dena.com/images/manga/', $upcomingItem->getImageUrl());
 }
 /**
  * Fetch Manga Recently Added to MAL.
  *
  * Gets a list of manga that were recently added to the MyAnimeList website. The get
  * variable "page" is used to select the set of results to return (in a default of 30
  * items per set). An invalid or missing value defaults to page 1.
  *
  * @param string  $apiVersion The API version of the request
  * @param Request $request    Contains all the needed information to get the list.
  *
  * @return View
  */
 public function getMangaJustaddedAction($apiVersion, Request $request)
 {
     // http://myanimelist.net/anime.php?o=9&c[]=a&c[]=b&c[]=c&c[]=d&c[]=e&c[]=f&c[]=g&cv=2&w=1&show=#{page}
     $page = (int) $request->query->get('page');
     if ($page <= 0) {
         $page = 1;
     }
     $downloader = $this->get('atarashii_api.communicator');
     try {
         $mangacontent = $downloader->fetch('/manga.php?o=9&c[]=a&c[]=b&c[]=c&c[]=d&c[]=e&c[]=f&c[]=g&cv=2&w=1&show=' . ($page * 20 - 20));
     } catch (Exception\CurlException $e) {
         return $this->view(array('error' => 'network-error'), 500);
     }
     $response = new Response();
     $serializationContext = SerializationContext::create();
     $serializationContext->setVersion($apiVersion);
     //For compatibility, API 1.0 explicitly passes null parameters.
     if ($apiVersion == '1.0') {
         $serializationContext->setSerializeNull(true);
     }
     $response->setPublic();
     $response->setMaxAge(10800);
     //Three hours
     $response->headers->addCacheControlDirective('must-revalidate', true);
     $response->setEtag('manga/just_added?page=' . urlencode($page));
     //Also, set "expires" header for caches that don't understand Cache-Control
     $date = new \DateTime();
     $date->modify('+10800 seconds');
     //Three hours
     $response->setExpires($date);
     if (strpos($mangacontent, 'No titles that matched') !== false) {
         $view = $this->view(array('error' => 'not-found'));
         $view->setResponse($response);
         $view->setStatusCode(404);
         return $view;
     } else {
         $Justaddedmanga = Upcoming::parse($mangacontent, 'manga');
         $view = $this->view($Justaddedmanga);
         $view->setSerializationContext($serializationContext);
         $view->setResponse($response);
         $view->setStatusCode(200);
         return $view;
     }
 }
 /**
  * @param         $apiVersion  The API version of the request
  * @param         $requestType The anime or manga request string
  * @param Request $request     HTTP Request object
  *
  * @return \FOS\RestBundle\View\View
  */
 public function getBrowseAction($apiVersion, $requestType, Request $request)
 {
     $downloader = $this->get('atarashii_api.communicator');
     $page = (int) $request->query->get('page');
     if ($page <= 0) {
         $page = 1;
     }
     // Create URL parts supported by MAL
     $pagePart = '&show=' . ($page * 50 - 50);
     $keyword = '&q=' . $request->query->get('keyword');
     $score = '&score=' . (int) $request->query->get('score');
     $reverse = '&w=' . (int) $request->query->get('reverse');
     $rating = '&r=' . (int) $request->query->get('rating');
     $genreType = '&gx=' . (int) $request->query->get('genre_type');
     $status = '&status=' . $this->getStatusId($request->query->get('status'));
     $endDateArray = explode('-', $request->query->get('end_date'));
     if (count($endDateArray) == 3) {
         $endDate = '&ey=' . $endDateArray[0] . '&em=' . $endDateArray[1] . '&ed=' . $endDateArray[2];
     } else {
         $endDate = '';
     }
     $startDateArray = explode('-', $request->query->get('start_date'));
     if (count($startDateArray) == 3) {
         $startDate = '&sy=' . $startDateArray[0] . '&sm=' . $startDateArray[1] . '&sd=' . $startDateArray[2];
     } else {
         $startDate = '';
     }
     if ($requestType === 'anime') {
         $type = '&type=' . Anime::getTypeId($request->query->get('type'));
         $genres = Anime::getGenresId($request->query->get('genres'));
         $sort = '&o=' . Anime::getColumnId($request->query->get('sort'), $requestType);
     } else {
         $type = '&type=' . Manga::getTypeId($request->query->get('type'));
         $genres = Manga::getGenresId($request->query->get('genres'));
         $sort = '&o=' . Manga::getColumnId($request->query->get('sort'), $requestType);
     }
     // Combine all URL parts for the request
     $url = $genres . $sort . $reverse . $endDate . $startDate . $rating . $status . $type . $keyword . $score . $genreType . $pagePart;
     try {
         $content = $downloader->fetch('/' . $requestType . '.php?c[]=a&c[]=b&c[]=c&c[]=d&c[]=e&c[]=f&c[]=g&c[]=g' . $url);
     } catch (Exception\CurlException $e) {
         return $this->view(array('error' => 'network-error'), 500);
     } catch (Exception\ClientErrorResponseException $e) {
         $content = $e->getResponse();
     }
     $response = new Response();
     $serializationContext = SerializationContext::create();
     $serializationContext->setVersion($apiVersion);
     $response->setPublic();
     $response->setMaxAge(86400);
     //One day
     $response->headers->addCacheControlDirective('must-revalidate', true);
     $response->setEtag($type . '/' . $requestType . '?' . $url);
     //Also, set "expires" header for caches that don't understand Cache-Control
     $date = new \DateTime();
     $date->modify('+86400 seconds');
     //One day
     $response->setExpires($date);
     // MAL does contain a bug where excluded genres allow the same amount of pages as normal without warning
     // To avoid issues we check if the page number does match the content page number.
     preg_match('/>\\[(\\d+?)\\]/', $content, $matches);
     if (strpos($content, 'No titles that matched') !== false || strpos($content, 'This page doesn\'t exist') !== false) {
         return $this->view(array('error' => 'not-found'), 404);
     } else {
         if (count($matches) > 1 && (int) $matches[1] !== $page) {
             return $this->view(array(), 200);
         } else {
             //MAL now returns 404 on a single result. Workaround
             if (method_exists($content, 'getStatusCode') && $content->getStatusCode() === 404) {
                 $location = $content->getHeader('Location');
                 try {
                     $content = $downloader->fetch($location);
                     if ($type === 'anime') {
                         $searchResult = array(AnimeParser::parse($content));
                     } else {
                         $searchResult = array(MangaParser::parse($content));
                     }
                 } catch (Exception\CurlException $e) {
                     return $this->view(array('error' => 'network-error'), 500);
                 }
             } else {
                 if ($downloader->wasRedirected()) {
                     if ($type === 'anime') {
                         $searchResult = array(AnimeParser::parse($content));
                     } else {
                         $searchResult = array(MangaParser::parse($content));
                     }
                 } else {
                     $searchResult = Upcoming::parse($content, $requestType);
                 }
             }
             $view = $this->view($searchResult);
             $view->setSerializationContext($serializationContext);
             $view->setResponse($response);
             $view->setStatusCode(200);
             return $view;
         }
     }
 }
 /**
  * Request search data using the unOfficial.
  *
  * With the unOfficial way the API will get the data from the search page instead of the official API.
  *
  * @param $type       The type is a string which can be 'anime' or 'manga'
  * @param $page       Integer which is used to get the desired page
  * @param $query      The title or keywords to seach for the record
  * @param $apiVersion The API version which was used for the request
  *
  * @return \FOS\RestBundle\View\View
  */
 private function unOfficialSearch($type, $page, $query, $apiVersion)
 {
     // http://myanimelist.net/anime.php?c[]=a&c[]=b&c[]=c&c[]=d&c[]=e&c[]=f&c[]=g&q=#{name}&show=#{page}
     // http://myanimelist.net/manga.php?c[]=a&c[]=b&c[]=c&c[]=d&c[]=e&c[]=f&c[]=g&q=#{name}&show=#{page}
     if ($page <= 0) {
         $page = 1;
     }
     $downloader = $this->get('atarashii_api.communicator');
     try {
         $content = $downloader->fetch('/' . $type . '.php?c[]=a&c[]=b&c[]=c&c[]=d&c[]=e&c[]=f&c[]=g&q=' . $query . '&show=' . ($page * 50 - 50));
     } catch (Exception\CurlException $e) {
         return $this->view(array('error' => 'network-error'), 500);
     } catch (Exception\ClientErrorResponseException $e) {
         //MAL now returns 404 on searches without results.
         //We still need the content for logic purposes.
         $content = $e->getResponse();
     }
     $response = new Response();
     $serializationContext = SerializationContext::create();
     $serializationContext->setVersion($apiVersion);
     $response->setPublic();
     $response->setMaxAge(3600);
     //One hour
     $response->headers->addCacheControlDirective('must-revalidate', true);
     $response->setEtag($type . '/search?q=' . urlencode($query) . 'page=' . $page);
     //Also, set "expires" header for caches that don't understand Cache-Control
     $date = new \DateTime();
     $date->modify('+3600 seconds');
     //One hour
     $response->setExpires($date);
     if (strpos($content, 'No titles that matched') !== false || strpos($content, 'This page doesn\'t exist') !== false) {
         $view = $this->view(array('error' => 'not-found'));
         $view->setResponse($response);
         $view->setStatusCode(404);
         return $view;
     } else {
         //For compatibility, API 1.0 explicitly passes null parameters.
         if ($apiVersion == '1.0') {
             $serializationContext->setSerializeNull(true);
         }
         //MAL now returns 404 on a single result. Workaround
         if (method_exists($content, 'getStatusCode') && $content->getStatusCode() === 404) {
             $location = $content->getHeader('Location');
             try {
                 $content = $downloader->fetch($location);
                 if ($type === 'anime') {
                     $searchResult = array(AnimeParser::parse($content));
                 } else {
                     $searchResult = array(MangaParser::parse($content));
                 }
             } catch (Exception\CurlException $e) {
                 return $this->view(array('error' => 'network-error'), 500);
             }
         } else {
             if ($downloader->wasRedirected()) {
                 if ($type === 'anime') {
                     $searchResult = array(AnimeParser::parse($content));
                 } else {
                     $searchResult = array(MangaParser::parse($content));
                 }
             } else {
                 $searchResult = Upcoming::parse($content, $type);
             }
         }
         $view = $this->view($searchResult);
         $view->setSerializationContext($serializationContext);
         $view->setResponse($response);
         $view->setStatusCode(200);
         return $view;
     }
 }