productList = $productList; $this->block = $block; $this->contextManager = $contextManager; } public function updateEditableContent(int $id, array $data): bool { return $this->getClient()->editableContent->update($id, $data)['result'] ?? false; } public function updateProduct(int $id, array $data): array { return $this->getClient()->product ->addSelection(['descriptionPlus' => ['id']]) ->update($id, $data) ?? []; } public function updateProductLinks(int $externalProductId, \Product $product): void { $links = []; foreach ($product->links ?? [] as $link) { $links[] = new LinkItem( $link['title'], $link['link'], $link['type'] ); } $this->client->product->updateLinks($externalProductId, $links); } public function updateProductRelated(int $externalProductId, \Product $product): void { $relatedProducts = []; foreach ($product->products_related ?? [] as $item) { if (empty($item->code)) { continue; } if ($relatedExternalId = $this->getProductIdByCode($item->code)) { $relatedProducts[] = new RelatedItem($relatedExternalId); } } $this->client->product->updateRelated($externalProductId, $relatedProducts); } public function updateProductCollection(int $externalProductId, \Product $product): void { $collectionProducts = []; foreach ($product->collections['own'] ?? [] as $item) { if (empty($item->code)) { continue; } if ($relatedExternalId = $this->getProductIdByCode($item->code)) { $collectionProducts[] = new CollectionItem($relatedExternalId); } } $this->client->product->updateCollections($externalProductId, $collectionProducts); } public function updateProductTranslations(int $externalProductId, int $externalEditableContentId, string $language, \Product $product): void { $translation = sqlQueryBuilder() ->select('*') ->from('products_translations') ->where(Operator::equals(['id_product' => $product->id, 'id_language' => $language])) ->execute()->fetchAssociative(); $productData = []; if (!empty($translation['title'])) { $productData['title'] = $translation['title']; } if (!empty($translation['short_descr'])) { $productData['description'] = $translation['short_descr']; } if (!empty($translation['long_descr'])) { $productData['longDescription'] = $translation['long_descr']; } if (!empty($translation['figure'])) { $productData['visibility'] = $this->getProductVisibility($translation['figure']); } if (!empty($translation['meta_title']) || !empty($translation['meta_description']) || !empty($translation['meta_keywords'])) { $seoData = []; if (!empty($translation['meta_title'])) { $seoData['title'] = $translation['meta_title']; } if (!empty($translation['meta_description'])) { $seoData['description'] = $translation['meta_description']; } if (!empty($translation['meta_keywords'])) { $seoData['keywords'] = $translation['meta_keywords']; } $productData['seo'] = $seoData; } if (!empty($productData)) { $this->getClient()->product->translate($externalProductId, $language, $productData); } // prelozit popis+ if (!empty($product->id_block)) { $defaultBlocks = $this->getBlocks((int) $product->id_block); $translatedBlocks = $this->getBlocks((int) $product->id_block, $language); if (json_encode($defaultBlocks) !== json_encode($translatedBlocks)) { $this->getClient()->editableContent->translate( $externalEditableContentId, $language, $this->createEditableContentFromBlocks($translatedBlocks) ); } } } public function updateProductParameters(int $externalProductId, \Product $product): void { $parameterUpdates = []; foreach ($this->getParameters() as $externalParameter) { $parameterUpdates[$externalParameter['id']] = []; } foreach ($product->param as $parameter) { // pokud nenajdu parametr, tak ho vytvorim if (!($externalParameterId = ($this->getParameterByName($parameter['name'])['id'] ?? false))) { // nejdriv rozhodnu typ parametru switch ($parameter['value_type']) { case 'float': $type = 'NUMBER'; break; case 'char': $type = 'TEXT'; break; default: $type = 'LIST'; } // vytvorim parametr $externalParameterId = $this->createParameter($parameter['name'], $type, empty($parameter['unit']) ? null : $parameter['unit'] )['id']; } $parameterUpdates[$externalParameterId] = array_map(fn ($x) => $x['value'], $parameter['values']); } // aktualizuju parametry na nejhracce $productParameters = []; foreach ($parameterUpdates as $externalParameterId => $values) { $parameterType = $this->getParameterType($externalParameterId); $productParameters[] = new ProductParameter( $externalProductId, $externalParameterId, array_map(fn ($x) => new ParameterValue($x, $parameterType), $values) ); } $this->getClient()->product->updateParameterBulk($productParameters); } public function createParameter(string $name, string $type, ?string $unit = null): array { $result = $this->getClient()->parameter->create( [ 'name' => $name, 'type' => $type, 'unit' => $unit, ] )['parameterCreate']; // Pridam parametr do cache return $this->parametersCache[] = $result; } public function getSections(bool $force = false): array { if (!$force && $this->sectionsListCache) { return $this->sectionsListCache; } return $this->sectionsListCache = $this->getClient()->section->setSelection( [ 'id', 'name', 'visible', 'url', 'isVirtual', 'parent' => [ 'id', 'name', 'parent' => [ 'id', 'name', 'parent' => [ 'id', 'name', 'parent' => [ 'id', 'name', 'parent' => [ 'id', 'name', 'parent' => [ 'id', 'name', ], ], ], ], ], ], ] )->list()['items'] ?? []; } public function getSectionIdByPath(array $path): ?int { static $sectionsByKey = []; $createKey = function (array $path) { return StringUtil::slugify(implode('/', $path)); }; if (empty($sectionsByKey)) { $sections = $this->getSections(); foreach ($sections as $section) { $remotePath = $this->getRemoteSectionPath($section); $sectionsByKey[$createKey($remotePath)] = $section['id']; } } $key = $createKey($path); return $sectionsByKey[$key] ?? null; } public function getRemoteSectionPath(array $section): array { $path = []; $currentSection = $section; while ($currentSection) { $path[$currentSection['id']] = $currentSection['name']; $currentSection = $currentSection['parent']; } return array_reverse($path, true); } public function getProducers(): array { if (!empty($this->producersListCache)) { return $this->producersListCache; } return $this->producersListCache = $this->client->producer->list()['items'] ?? []; } public function getParameters(bool $force = false): array { if (!$force && !empty($this->parametersCache)) { return $this->parametersCache; } return $this->parametersCache = $this->getClient()->parameter->list()['items'] ?? []; } public function getParameterType(int $parameterId): string { static $parameterTypes; if (!$parameterTypes) { $parameterTypes = Mapping::mapKeys($this->getParameters(), fn ($k, $v) => [$v['id'], $v['type']]); } return $parameterTypes[$parameterId] ?? 'LIST'; } public function getParameterByName(string $name): ?array { $nameLower = mb_strtolower($name); foreach ($this->getParameters() as $parameter) { if (mb_strtolower($parameter['name']) === $nameLower) { return $parameter; } } return null; } public function getProducerIdByName(string $name): ?int { $nameLower = mb_strtolower($name); foreach ($this->getProducers() as $producer) { if (mb_strtolower($producer['name']) === $nameLower) { return $producer['id']; } } return null; } public function getProductIdByCode(string $code): ?int { return $this->getClient()->product->getByCode($code)['id'] ?? null; } public function getProductVisibility(string $visibility): string { switch ($visibility) { case 'Y': return ProductVisibility::VISIBLE; case 'O': return ProductVisibility::CLOSED; default: return ProductVisibility::HIDDEN; } } public function getBlocks(int $rootBlockId, ?string $language = null): ?array { $language = $language ?: Contexts::get(LanguageContext::class)->getDefaultId(); return $this->contextManager->activateContexts([LanguageContext::class => $language], function () use ($rootBlockId) { return $this->block->getBlocks($rootBlockId); }); } public function getProduct(int $productId, ?string $language = null): ?\Product { $productList = clone $this->productList; $productList->andSpec(Operator::equals(['p.id' => $productId])); $productList->fetchParameters(); $productList->fetchSections(); $productList->fetchLinks(); $productList->fetchCollections(); $productList->fetchProductsRelated(); $productList->fetchProducers(); $language = $language ?: Contexts::get(LanguageContext::class)->getDefaultId(); $products = $this->contextManager->activateContexts([LanguageContext::class => $language], function () use ($productList) { return $productList->getProducts(); }); if (empty($products[$productId])) { return null; } return $products[$productId]; } public function createEditableContentFromBlocks(array $blocks): array { $data = [ 'areas' => [], 'overwrite' => true, ]; foreach ($blocks as $block) { $data['areas'][] = [ 'id' => null, 'name' => $block['name'], 'data' => $block['json_content'] ?: '[]', ]; } return $data; } public function getClient(): Client { if (!$this->client) { $this->client = new Client( self::GRAPHQL_URL, self::GRAPHQL_ACCESS_TOKEN ); } return $this->client; } }