From 5256a41b9a1e344ce2583cd6be0477f684711f4f Mon Sep 17 00:00:00 2001 From: Ryan Holt Date: Fri, 5 Feb 2016 12:46:58 -0500 Subject: [PATCH 1/3] Added contains query string parameter to handle SQL Like statements, which works well for multiselects and the like --- .gitignore | 1 + Extension.php | 60 ++++++++++++++++++++++++++------------------------- readme.md | 1 + 3 files changed, 33 insertions(+), 29 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..723ef36 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea \ No newline at end of file diff --git a/Extension.php b/Extension.php index 6e18b56..7025445 100644 --- a/Extension.php +++ b/Extension.php @@ -44,17 +44,17 @@ public function initialize() $this->basePath = $this->app['paths']['canonical'] . $this->base; $this->app->get($this->base."/menu", [$this, 'jsonapi_menu']) - ->bind('jsonapi_menu'); + ->bind('jsonapi_menu'); $this->app->get($this->base."/search", [$this, 'jsonapi_search']) - ->bind('jsonapi_search_mixed'); + ->bind('jsonapi_search_mixed'); $this->app->get($this->base."/{contenttype}/search", [$this, 'jsonapi_search']) - ->bind('jsonapi_search'); + ->bind('jsonapi_search'); $this->app->get($this->base."/{contenttype}/{slug}/{relatedContenttype}", [$this, 'jsonapi']) - ->value('relatedContenttype', null) - ->assert('slug', '[a-zA-Z0-9_\-]+') - ->bind('jsonapi'); + ->value('relatedContenttype', null) + ->assert('slug', '[a-zA-Z0-9_\-]+') + ->bind('jsonapi'); $this->app->get($this->base."/{contenttype}", [$this, 'jsonapi_list']) - ->bind('jsonapi_list'); + ->bind('jsonapi_list'); } // ------------------------------------------------------------------------- @@ -126,6 +126,25 @@ public function jsonapi_list(Request $request, $contenttype) } } + // Handle $contains[], this modifies the $where[] clause to search using Like. + if ($contains = $request->get('contains')) { + foreach ($contains as $key => $value) { + if (!in_array($key, $allFields)) { + return $this->responseInvalidRequest([ + 'detail' => "Parameter [$key] does not exist for contenttype with name [$contenttype]." + ]); + } + + $values = explode(",", $value); + + foreach ($values as $i => $item) { + $values[$i] = '%"' . $item .'"%'; + } + + $where[$key] = implode(' || ', $values); + } + } + // If `returnsingle` is not set to false, then a single result will not // result in an array. $where['returnsingle'] = false; @@ -715,11 +734,11 @@ private function cleanItem($item, $fields = []) foreach($item->contenttype['fields'] as $key => $field) { if ($field['type'] == 'imagelist' && !empty($attributes[$key])) { - foreach ($attributes[$key] as &$image) { - $image['url'] = $this->makeAbsolutePathToImage($image['filename']); + foreach ($attributes[$key] as &$value) { + $value['url'] = $this->makeAbsolutePathToImage($value['filename']); if (is_array($this->config['thumbnail'])) { - $image['thumbnail'] = $this->makeAbsolutePathToThumbnail($image['filename']); + $value['thumbnail'] = $this->makeAbsolutePathToThumbnail($value['filename']); } } } @@ -746,23 +765,6 @@ private function cleanItem($item, $fields = []) } if (!empty($attributes)) { - - // Recursively walk the array.. - array_walk_recursive($attributes, function(&$item) { - // Make sure that any \Twig_Markup objects are cast to plain strings. - if ($item instanceof \Twig_Markup) { - $item = $item->__toString(); - } - - // Handle replacements. - if (!empty($this->config['replacements'])) { - foreach ($this->config['replacements'] as $from => $to) { - $item = str_replace($from, $to, $item); - } - } - - }); - $values['attributes'] = $attributes; } @@ -1015,7 +1017,7 @@ private function makeAbsolutePathToImage($filename = '') $this->app['paths']['canonical'], $this->app['paths']['files'], $filename - ); + ); } private function makeAbsolutePathToThumbnail($filename = '') @@ -1025,7 +1027,7 @@ private function makeAbsolutePathToThumbnail($filename = '') $this->config['thumbnail']['width'], $this->config['thumbnail']['height'], $filename - ); + ); } } diff --git a/readme.md b/readme.md index 7a35eab..89ac31d 100644 --- a/readme.md +++ b/readme.md @@ -120,6 +120,7 @@ parameters appended to the URL): |`include` | Fetches all the related records of the specified contenttype(s) of the record(s) in the `included` field of the JSON response. Separate multiple contenttypes with a comma. Example: `include=pages`. | |`fields[]` | Set the fields that are shown in the response per specified contenttype. Separate multiple fields with commas. Multiple `fields[]` parameters are possible. Example: `fields[entries]=slug,teaser`. | |`filter[]` | Filter records where a certain field must be equal to the specified `{value}`. Multiple `filter[]` parameters are possible. Example: `filter[id]=1,2`. | +|`contains[]` | Filter records where a certain field must contain the specified `{value}`. Multiple `contains[]` parameters are possible. Example: `contains[id]=1,2`. | ### Additional Queries From c19be862c01f48a8a08ac9c88a2a0b4a8a2e57f7 Mon Sep 17 00:00:00 2001 From: Ryan Holt Date: Fri, 5 Feb 2016 12:49:59 -0500 Subject: [PATCH 2/3] refactoring to prevent too many superfluous changes in the PR --- Extension.php | 45 +++++++++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/Extension.php b/Extension.php index 7025445..a4af5c3 100644 --- a/Extension.php +++ b/Extension.php @@ -44,17 +44,17 @@ public function initialize() $this->basePath = $this->app['paths']['canonical'] . $this->base; $this->app->get($this->base."/menu", [$this, 'jsonapi_menu']) - ->bind('jsonapi_menu'); + ->bind('jsonapi_menu'); $this->app->get($this->base."/search", [$this, 'jsonapi_search']) - ->bind('jsonapi_search_mixed'); + ->bind('jsonapi_search_mixed'); $this->app->get($this->base."/{contenttype}/search", [$this, 'jsonapi_search']) - ->bind('jsonapi_search'); + ->bind('jsonapi_search'); $this->app->get($this->base."/{contenttype}/{slug}/{relatedContenttype}", [$this, 'jsonapi']) - ->value('relatedContenttype', null) - ->assert('slug', '[a-zA-Z0-9_\-]+') - ->bind('jsonapi'); + ->value('relatedContenttype', null) + ->assert('slug', '[a-zA-Z0-9_\-]+') + ->bind('jsonapi'); $this->app->get($this->base."/{contenttype}", [$this, 'jsonapi_list']) - ->bind('jsonapi_list'); + ->bind('jsonapi_list'); } // ------------------------------------------------------------------------- @@ -128,7 +128,7 @@ public function jsonapi_list(Request $request, $contenttype) // Handle $contains[], this modifies the $where[] clause to search using Like. if ($contains = $request->get('contains')) { - foreach ($contains as $key => $value) { + foreach($contains as $key => $value) { if (!in_array($key, $allFields)) { return $this->responseInvalidRequest([ 'detail' => "Parameter [$key] does not exist for contenttype with name [$contenttype]." @@ -137,7 +137,7 @@ public function jsonapi_list(Request $request, $contenttype) $values = explode(",", $value); - foreach ($values as $i => $item) { + foreach($values as $i => $item) { $values[$i] = '%"' . $item .'"%'; } @@ -734,11 +734,11 @@ private function cleanItem($item, $fields = []) foreach($item->contenttype['fields'] as $key => $field) { if ($field['type'] == 'imagelist' && !empty($attributes[$key])) { - foreach ($attributes[$key] as &$value) { - $value['url'] = $this->makeAbsolutePathToImage($value['filename']); + foreach ($attributes[$key] as &$image) { + $image['url'] = $this->makeAbsolutePathToImage($image['filename']); if (is_array($this->config['thumbnail'])) { - $value['thumbnail'] = $this->makeAbsolutePathToThumbnail($value['filename']); + $image['thumbnail'] = $this->makeAbsolutePathToThumbnail($image['filename']); } } } @@ -765,6 +765,23 @@ private function cleanItem($item, $fields = []) } if (!empty($attributes)) { + + // Recursively walk the array.. + array_walk_recursive($attributes, function(&$item) { + // Make sure that any \Twig_Markup objects are cast to plain strings. + if ($item instanceof \Twig_Markup) { + $item = $item->__toString(); + } + + // Handle replacements. + if (!empty($this->config['replacements'])) { + foreach ($this->config['replacements'] as $from => $to) { + $item = str_replace($from, $to, $item); + } + } + + }); + $values['attributes'] = $attributes; } @@ -1017,7 +1034,7 @@ private function makeAbsolutePathToImage($filename = '') $this->app['paths']['canonical'], $this->app['paths']['files'], $filename - ); + ); } private function makeAbsolutePathToThumbnail($filename = '') @@ -1027,7 +1044,7 @@ private function makeAbsolutePathToThumbnail($filename = '') $this->config['thumbnail']['width'], $this->config['thumbnail']['height'], $filename - ); + ); } } From 8fbe70d18afcdc84f9b05444fa037e4f262e0b74 Mon Sep 17 00:00:00 2001 From: Ryan Holt Date: Fri, 5 Feb 2016 13:15:29 -0500 Subject: [PATCH 3/3] Fixes to PSR-2 compliancy; --- Extension.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Extension.php b/Extension.php index a4af5c3..09aecbe 100644 --- a/Extension.php +++ b/Extension.php @@ -128,7 +128,7 @@ public function jsonapi_list(Request $request, $contenttype) // Handle $contains[], this modifies the $where[] clause to search using Like. if ($contains = $request->get('contains')) { - foreach($contains as $key => $value) { + foreach ($contains as $key => $value) { if (!in_array($key, $allFields)) { return $this->responseInvalidRequest([ 'detail' => "Parameter [$key] does not exist for contenttype with name [$contenttype]." @@ -137,8 +137,8 @@ public function jsonapi_list(Request $request, $contenttype) $values = explode(",", $value); - foreach($values as $i => $item) { - $values[$i] = '%"' . $item .'"%'; + foreach ($values as $i => $item) { + $values[$i] = '%' . $item .'%'; } $where[$key] = implode(' || ', $values);