Closed truecolintracy closed 4 years ago
Hi @truecolintray is it possible you PM me your shopify credentials of the API you use for the plugin? Or maybe create a separate app inside of shopify-ui with less authorizations. Because I do not have an account to test/reproduce this with. mail: maier-niklas@t-online.de
Would just like to add that I have the same issue.
It looks like the API now returns results in paginated form with links to the next (and prev) pages in the response header (the key is 'Link'). You also need to switch to the latest version of the API to get the links returned in the header.
Not sure why the functionality changed in the older version of the API as well as the new version?
I have a really hacky temporary fix - it is not advisable to use this in production but it demonstrates the issue at least. It's just proof of concept. It would be wise to either use a while loop with a reliable break function or maybe run another query to get max results and then use that to control the expected number of loops in order to avoid it looping too long. At the moment it's got a hard coded cap of 10... not pretty.
`/**
namespace shopify\services;
use yii\base\Component;
class ShopifyService extends Component {
/**
@return bool */ public function getProducts($options = array()) { $all_products = array(); $next_link = null;
// Theoretically this should be a do while loop because we don't // know how many iterations it's going to take. // Am actually using a for loop so if the break clause fails // we don't end up in infinite loop territory. for ($i = 0; $i <= 10; $i++) { // Make the request and add any found products to the master array. $response = $this->getProductsPageResponse($options, $next_link); $items = json_decode($response->getBody()->getContents(), true); $products = $items['products']; $all_products = array_merge($all_products, $products); // See if we have any link headers. $next_link_found = false; if ($header_links = $response->getHeader('Link')) { $header_link_array = explode(', ', $header_links[0]); foreach ($header_link_array as $header_link) { if (strpos($header_link, 'rel="next"') !== false) { $next_link_found = true; // Need to sanitize the link. $link_explode = explode('>', $header_link); $link = $link_explode[0]; $link = substr($link, 9); // Assign the new link to the old link variable. $next_link = $link; } } // If no next link then break out of loop. if (!$next_link_found) { break; } } }
// Return all the products from all the pages. return $all_products; }
/**
@return bool */ public function getProductsPageResponse($options = array(), $url_override = null) { $settings = \shopify\Shopify::getInstance()->getSettings();
$query = http_build_query($options); // $url = $this->getShopifyUrl($settings->allProductsEndpoint . '?' . $query, $settings);
if (!is_null($url_override)) { $url = 'https://' . $settings->apiKey . ':' . $settings->password . '@' . $url_override; } else { $url = 'https://' . $settings->apiKey . ':' . $settings->password . '@' . $settings->hostname . '/admin/api/2019-10/products.json'; }
try { $client = new \GuzzleHttp\Client(); $response = $client->request('GET', $url); if ($response->getStatusCode() !== 200) { return false; } return $response; } catch(\Exception $e) { return false; } }
/**
@return bool */ public function getProductById($options = array()) { $settings = \shopify\Shopify::getInstance()->getSettings();
$id = $options['id']; $fields = isset($options['fields']) ? '?fields=' . $options['fields'] : ''; $url = $this->getShopifyUrl($settings->singleProductEndpoint . $id . '.json' . $fields, $settings);
try { $client = new \GuzzleHttp\Client(); $response = $client->request('GET', $url);
if ($response->getStatusCode() !== 200) {
return false;
}
$items = json_decode($response->getBody()->getContents(), true);
return $items['product'];
} catch(\Exception $e) { return false; } }
/**
@nmaier95, any progress on this? I love the plugin but we have lots of products and only getting the first page is not enough.
@nmaier95, @truecolintracy, and @abswdsmn, take a look at my PR here: https://github.com/nmaier95/craft-shopify-product-fetcher/pull/9
If you have more products than the 50 displayed on the first page of the query then only the first page will show up.
I was able to add a
limit=250
to the query, but this is a bit of a hack fix and seems to only allow that value as the top limit.