From 71ffa9b781a5929af8e79d60739ca6cf69a9c4eb Mon Sep 17 00:00:00 2001 From: Paulo Margarido <64600052+paulomarg@users.noreply.github.com> Date: Thu, 7 Apr 2022 10:21:58 -0400 Subject: [PATCH 1/2] Load unknown attributes from the API --- src/Rest/Base.php | 104 ++++++++++++------------- tests/Clients/BaseRestResourceTest.php | 21 +++++ 2 files changed, 73 insertions(+), 52 deletions(-) diff --git a/src/Rest/Base.php b/src/Rest/Base.php index 1016af2e..d0f8c17c 100644 --- a/src/Rest/Base.php +++ b/src/Rest/Base.php @@ -98,6 +98,44 @@ public static function getPreviousPageInfo() return static::$PREV_PAGE_QUERY; } + public function toArray(): array + { + $data = []; + + foreach ($this->getProperties() as $prop) { + if (in_array($prop, static::$READ_ONLY_ATTRIBUTES)) { + continue; + } + + $includeProp = !empty($this->$prop) || array_key_exists($prop, $this->setProps); + if (self::isHasManyAttribute($prop)) { + if ($includeProp) { + $data[$prop] = []; + /** @var self $assoc */ + foreach ($this->$prop as $assoc) { + if (empty($assoc) || is_array($assoc)) { + array_push($data[$prop], $assoc); + } else { + array_push($data[$prop], $assoc->toArray()); + } + } + } + } elseif (self::isHasOneAttribute($prop)) { + if ($includeProp) { + if (empty($this->$prop) || is_array($this->$prop)) { + $data[$prop] = $this->$prop; + } else { + $data[$prop] = $this->$prop->toArray(); + } + } + } elseif ($includeProp) { + $data[$prop] = $this->$prop; + } + } + + return $data; + } + protected static function getJsonBodyName(): string { $className = preg_replace("/^([A-z_0-9]+\\\)*([A-z_]+)/", "$2", static::class); @@ -232,12 +270,16 @@ private static function createInstancesFromResponse(RestResponse $response, Sess $pluralClass = self::pluralize($className); if (!empty($body)) { - if (array_key_exists($className, $body)) { - array_push($objects, self::createInstance($body[$className], $session)); - } elseif (array_key_exists($pluralClass, $body)) { + if (array_key_exists($pluralClass, $body)) { foreach ($body[$pluralClass] as $entry) { array_push($objects, self::createInstance($entry, $session)); } + } elseif (array_key_exists($className, $body) && array_key_exists(0, $body[$className])) { + foreach ($body[$className] as $entry) { + array_push($objects, self::createInstance($entry, $session)); + } + } elseif (array_key_exists($className, $body)) { + array_push($objects, self::createInstance($body[$className], $session)); } } @@ -278,15 +320,11 @@ private static function setInstanceData(self &$instance, array $data): void { $instance->originalState = []; - foreach ($instance->getProperties() as $prop) { - if (!array_key_exists($prop, $data)) { - continue; - } - + foreach ($data as $prop => $value) { if (self::isHasManyAttribute($prop)) { $attrList = []; - if (!empty($data[$prop])) { - foreach ($data[$prop] as $elementData) { + if (!empty($value)) { + foreach ($value as $elementData) { array_push( $attrList, static::$HAS_MANY[$prop]::createInstance($elementData, $instance->session) @@ -296,15 +334,15 @@ private static function setInstanceData(self &$instance, array $data): void $instance->setProperty($prop, $attrList); } elseif (self::isHasOneAttribute($prop)) { - if (!empty($data[$prop])) { + if (!empty($value)) { $instance->setProperty( $prop, - static::$HAS_ONE[$prop]::createInstance($data[$prop], $instance->session) + static::$HAS_ONE[$prop]::createInstance($value, $instance->session) ); } } else { - $instance->setProperty($prop, $data[$prop]); - $instance->originalState[$prop] = $data[$prop]; + $instance->setProperty($prop, $value); + $instance->originalState[$prop] = $value; } } } @@ -356,42 +394,4 @@ private function getProperties(): array return array_unique(array_merge($props, array_keys($this->setProps))); } - - private function toArray(): array - { - $data = []; - - foreach ($this->getProperties() as $prop) { - if (in_array($prop, static::$READ_ONLY_ATTRIBUTES)) { - continue; - } - - $includeProp = !empty($this->$prop) || array_key_exists($prop, $this->setProps); - if (self::isHasManyAttribute($prop)) { - if ($includeProp) { - $data[$prop] = []; - /** @var self $assoc */ - foreach ($this->$prop as $assoc) { - if (empty($assoc) || is_array($assoc)) { - array_push($data[$prop], $assoc); - } else { - array_push($data[$prop], $assoc->toArray()); - } - } - } - } elseif (self::isHasOneAttribute($prop)) { - if ($includeProp) { - if (empty($this->$prop) || is_array($this->$prop)) { - $data[$prop] = $this->$prop; - } else { - $data[$prop] = $this->$prop->toArray(); - } - } - } elseif ($includeProp) { - $data[$prop] = $this->$prop; - } - } - - return $data; - } } diff --git a/tests/Clients/BaseRestResourceTest.php b/tests/Clients/BaseRestResourceTest.php index c26f3c22..49cc405d 100644 --- a/tests/Clients/BaseRestResourceTest.php +++ b/tests/Clients/BaseRestResourceTest.php @@ -264,6 +264,27 @@ public function testSavesWithChildren() $resource->save(); } + public function testLoadsUnknownAttribute() + { + $body = ["fake_resource" => ["attribute" => "value", "unknown?" => "some-value"]]; + + $this->mockTransportRequests([ + new MockRequest( + $this->buildMockHttpResponse(200, json_encode($body)), + "{$this->prefix}/fake_resources/1.json", + "GET", + null, + ["X-Shopify-Access-Token: access-token"], + ), + ]); + + $resource = FakeResource::find($this->session, 1); + + $this->assertEquals("value", $resource->attribute); + $this->assertEquals("some-value", $resource->{"unknown?"}); + $this->assertEquals("some-value", $resource->toArray()["unknown?"]); + } + public function testSavesWithUnknownAttribute() { $body = ["fake_resource" => ["unknown" => "some-value"]]; From 50116a7177f52567122e07dec5cdb358b36033ee Mon Sep 17 00:00:00 2001 From: Paulo Margarido <64600052+paulomarg@users.noreply.github.com> Date: Thu, 7 Apr 2022 10:27:05 -0400 Subject: [PATCH 2/2] Updating changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index dc3686d8..9af6a0e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). ### Added - [#168](https://github.com/Shopify/shopify-php-api/pull/168) Allow REST resources to configure a deny list of attributes to be excluded when saving +- [#169](https://github.com/Shopify/shopify-php-api/pull/169) Allow loading dynamic fields returned by the API, and fix an issue when loading object arrays from API response data ## v2.0.0 - 2022-04-04