diff --git a/lib/Service/RecipeService.php b/lib/Service/RecipeService.php index 06efffda..b790bb0a 100644 --- a/lib/Service/RecipeService.php +++ b/lib/Service/RecipeService.php @@ -2,6 +2,9 @@ namespace OCA\Cookbook\Service; +use Exception; +use OCP\Files\NotFoundException; +use OCP\Files\NotPermittedException; use OCP\Image; use OCP\IConfig; use OCP\Files\IRootFolder; @@ -9,16 +12,23 @@ use OCP\Files\FileInfo; use OCP\Files\File; use OCP\Files\Folder; use OCP\IDBConnection; - use OCA\Cookbook\Db\RecipeDb; +use OCP\PreConditionNotMetException; -class RecipeService { +/** + * Main service class for the cookbook app. + * + * @package OCA\Cookbook\Service + */ +class RecipeService +{ private $root; private $userId; private $db; private $config; - public function __construct($UserId, IRootFolder $root, RecipeDb $db, IConfig $config) { + public function __construct(string $UserId, IRootFolder $root, RecipeDb $db, IConfig $config) + { $this->userId = $UserId; $this->root = $root; $this->db = $db; @@ -26,14 +36,19 @@ class RecipeService { } /** + * Get a recipe by its folder id. + * * @param int $id * - * @return array + * @return array|null */ - public function getRecipeById($id) { + public function getRecipeById(int $id) + { $file = $this->getRecipeFileByFolderId($id); - if(!$file) { return null; } + if (!$file) { + return null; + } return $this->parseRecipeFile($file); } @@ -43,20 +58,27 @@ class RecipeService { * * @param int $id * - * @return \OCP\Files\File + * @return File|null */ - public function getRecipeFileByFolderId($id) { - $user_folder = $this->getFolderForUser(); - $recipe_folder = $user_folder->getById($id); + public function getRecipeFileByFolderId(int $id) + { + $userFolder = $this->getFolderForUser(); + $recipeFolder = $userFolder->getById($id); - if(count($recipe_folder) <= 0) { return null; } + if (count($recipeFolder) <= 0) { + return null; + } - $recipe_folder = $recipe_folder[0]; + $recipeFolder = $recipeFolder[0]; - if($recipe_folder instanceof Folder === false) { return null; } + if ($recipeFolder instanceof Folder === false) { + return null; + } - foreach($recipe_folder->getDirectoryListing() as $file) { - if($this->isRecipeFile($file)) { return $file; } + foreach ($recipeFolder->getDirectoryListing() as $file) { + if ($this->isRecipeFile($file)) { + return $file; + } } return null; @@ -69,13 +91,14 @@ class RecipeService { * @param array $json * @param string $key */ - private function validateDuration($json, $key) { + private function validateDuration($json, $key) + { // Make sure we have a string and valid DateInterval // regex validation from here: https://stackoverflow.com/a/32045167 $interval_regex = "/^P(?!$)(\d+Y)?(\d+M)?(\d+W)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+S)?)?$/"; - if(isset($json[$key]) && is_string($json[$key])) { + if (isset($json[$key]) && is_string($json[$key])) { $time_string = $this->cleanUpString($json[$key]); - if(preg_match_all($interval_regex, $time_string)) { + if (preg_match_all($interval_regex, $time_string)) { $json[$key] = $time_string; } else { $json[$key] = ""; @@ -92,9 +115,14 @@ class RecipeService { * * @return array */ - public function checkRecipe($json) { - if(!$json) { throw new \Exception('Recipe array was null'); } - if(!isset($json['name']) || !$json['name']) { throw new \Exception('Field "name" is required'); } + public function checkRecipe($json) + { + if (!$json) { + throw new Exception('Recipe array was null'); + } + if (!isset($json['name']) || !$json['name']) { + throw new Exception('Field "name" is required'); + } // Make sure the schema.org fields are present $json['@context'] = 'http://schema.org'; @@ -104,19 +132,19 @@ class RecipeService { $json['name'] = $this->cleanUpString($json['name']); // Make sure that "image" is a string of the highest resolution image available - if(isset($json['image']) && $json['image']) { - if(is_array($json['image'])) { + if (isset($json['image']) && $json['image']) { + if (is_array($json['image'])) { // Get the image from a subproperty "url" - if(isset($json['image']['url'])) { + if (isset($json['image']['url'])) { $json['image'] = $json['image']['url']; - // Try to get the image with the highest resolution by adding together all numbers in the url + // Try to get the image with the highest resolution by adding together all numbers in the url } else { $images = $json['image']; $image_size = 0; - foreach($images as $img) { - if(is_array($img) && isset($img['url'])) { + foreach ($images as $img) { + if (is_array($img) && isset($img['url'])) { $img = $img['url']; } @@ -126,16 +154,16 @@ class RecipeService { $this_image_size = 0; - foreach($image_matches as $image_match) { - $this_image_size += (int) $image_match; + foreach ($image_matches as $image_match) { + $this_image_size += (int)$image_match; } - if($image_size === 0 || $this_image_size > $image_size) { + if ($image_size === 0 || $this_image_size > $image_size) { $json['image'] = $img; } } } - } else if(!is_string($json['image'])) { + } else if (!is_string($json['image'])) { $json['image'] = ''; } } else { @@ -146,11 +174,11 @@ class RecipeService { $json['image'] = stripslashes($json['image']); // Make sure that "recipeYield" is an integer which is at least 1 - if(isset($json['recipeYield']) && $json['recipeYield']) { + if (isset($json['recipeYield']) && $json['recipeYield']) { $yield = filter_var($json['recipeYield'], FILTER_SANITIZE_NUMBER_INT); - if($yield && $yield > 0) { - $json['recipeYield'] = (int) $yield; + if ($yield && $yield > 0) { + $json['recipeYield'] = (int)$yield; } else { $json['recipeYield'] = 1; } @@ -159,7 +187,7 @@ class RecipeService { } // Make sure that "keywords" is an array of unique strings - if(isset($json['keywords']) && is_string($json['keywords'])) { + if (isset($json['keywords']) && is_string($json['keywords'])) { $keywords = trim($json['keywords']); $keywords = trim($keywords, ','); $keywords = trim($keywords); @@ -176,13 +204,15 @@ class RecipeService { } // Make sure that "recipeIngredient" is an array of strings - if(isset($json['recipeIngredient']) && is_array($json['recipeIngredient'])) { + if (isset($json['recipeIngredient']) && is_array($json['recipeIngredient'])) { $ingredients = []; - foreach($json['recipeIngredient'] as $i => $ingredient) { + foreach ($json['recipeIngredient'] as $i => $ingredient) { $ingredient = $this->cleanUpString($ingredient); - if(!$ingredient) { continue; } + if (!$ingredient) { + continue; + } array_push($ingredients, $ingredient); } @@ -193,37 +223,41 @@ class RecipeService { $json['recipeIngredient'] = array_filter($json['recipeIngredient']); // Make sure that "recipeInstructions" is an array of strings - if(isset($json['recipeInstructions'])) { - if(is_array($json['recipeInstructions'])) { - foreach($json['recipeInstructions'] as $i => $step) { - if(is_string($step)) { + if (isset($json['recipeInstructions'])) { + if (is_array($json['recipeInstructions'])) { + foreach ($json['recipeInstructions'] as $i => $step) { + if (is_string($step)) { $json['recipeInstructions'][$i] = $this->cleanUpString($step, true); - } else if(is_array($step) && isset($step['text'])) { + } else if (is_array($step) && isset($step['text'])) { $json['recipeInstructions'][$i] = $this->cleanUpString($step['text'], true); } else { $json['recipeInstructions'][$i] = ''; } } - } else if(is_string($json['recipeInstructions'])) { + } else if (is_string($json['recipeInstructions'])) { $json['recipeInstructions'] = html_entity_decode($json['recipeInstructions']); $regex_matches = []; - preg_match_all('/<(p|li)>(.*?)<\/(p|li)>/', $json['recipeInstructions'], $regex_matches, PREG_SET_ORDER); + preg_match_all('/<(p|li)>(.*?)<\/(p|li)>/', $json['recipeInstructions'], $regex_matches, PREG_SET_ORDER); $instructions = []; - foreach($regex_matches as $regex_match) { - if(!$regex_match || !isset($regex_match[2])) { continue; } + foreach ($regex_matches as $regex_match) { + if (!$regex_match || !isset($regex_match[2])) { + continue; + } $step = $this->cleanUpString($regex_match[2]); - if(!$step) { continue; } + if (!$step) { + continue; + } array_push($instructions, $step); } - if(sizeof($instructions) > 0) { + if (sizeof($instructions) > 0) { $json['recipeInstructions'] = $instructions; } else { $json['recipeInstructions'] = explode(PHP_EOL, $json['recipeInstructions']); @@ -232,22 +266,22 @@ class RecipeService { $json['recipeInstructions'] = []; } } else { - $json['recipeInstructions'] = []; + $json['recipeInstructions'] = []; } - $json['recipeInstructions'] = array_filter($json['recipeInstructions'], function($v) { + $json['recipeInstructions'] = array_filter($json['recipeInstructions'], function ($v) { return !empty($v) && $v !== "\n" && $v !== "\r"; }); - // Make sure the 'description' is a string - if(isset($json['description']) && is_string($json['description'])) { - $json['description'] = $this->cleanUpString($json['description']); - } else { - $json['description'] = ""; - } + // Make sure the 'description' is a string + if (isset($json['description']) && is_string($json['description'])) { + $json['description'] = $this->cleanUpString($json['description']); + } else { + $json['description'] = ""; + } - // Make sure the 'url' is a URL, or blank - if(isset($json['url']) && $json['url']) { + // Make sure the 'url' is a URL, or blank + if (isset($json['url']) && $json['url']) { $url = filter_var($json['url'], FILTER_SANITIZE_URL); if (filter_var($url, FILTER_VALIDATE_URL) == false) { $url = ""; @@ -267,36 +301,47 @@ class RecipeService { /** * @param string $html * - * @return array + * @return array */ - private function parseRecipeHtml($html) { - if(!$html) { return null; } + private function parseRecipeHtml($html) + { + if (!$html) { + return null; + } //$html = str_replace(["\r", "\n", "\t"], '', $html); $json_matches = []; // Parse JSON preg_match_all('/