productLabelUtil = $this->get(ProductLabelUtil::class); $this->labelFilterSpecs = $this->get(LabelFilterSpecs::class); $this->productList = $this->get(ProductList::class); } protected function getDataSet() { return $this->getJsonDataSetFromFile(); } /** @dataProvider data_testProductLabelsMultiFetch */ public function testProductLabelsMultiFetch(?string $visibility, int $expectedLabelsCount, int $expectedVisibleLabelsCount, bool $loggedUser = false): void { if ($loggedUser) { $user = \User::createFromId(1); $user->activateUser(); } $products = $this->productList->andSpec(Operator::equals(['p.id' => 9411])) ->getProducts(); $products->fetchProductLabels($visibility); $product = $products->first(); $this->assertCount($expectedLabelsCount, $product->labels); $this->assertCount($expectedVisibleLabelsCount, array_filter($product->labels, fn ($x) => $x['is_visible'])); } public function data_testProductLabelsMultiFetch(): iterable { yield 'Vsechny aktivni stitky by mely byt nactene u produktu a vsechny i jako viditelne' => [null, 2, 2]; yield 'Vsechny stitky by mely byt nactene u produktu a vsechny i jako viditelne ' => ['all', 4, 4]; yield 'Detail produktu - celkove dva aktivni stitky, a oba se maji zobrazovat na detailu' => ['detail', 2, 2]; yield 'Seznam produktu - celkove dva aktivni stitky, ale jen jeden se ma zobrazovat na seznamu' => ['list', 2, 1]; yield 'Seznam - celkove dva aktivni stitky, ale jen jeden se ma zobrazovat na seznamu a uzivatel prihlaseny' => ['list', 3, 2, true]; } public function testAutomaticLabelAssignment() { $filterSpecs = $this->labelFilterSpecs->getSpecs(['active' => true, 'id' => 1]); $productLabelRelation = sqlQueryBuilder() ->select('*') ->from('product_labels_relation', 'plr') ->where(Operator::equals(['id_label' => 1])) ->execute() ->fetchAllAssociative(); $manualAssignedItem = $this->getProductByProperty($productLabelRelation, 9410); $this->assertCount(1, $productLabelRelation); $this->assertNotNull($manualAssignedItem); $this->assertEquals(0, $manualAssignedItem['generated']); $labels = sqlQueryBuilder() ->select('l.id, l.data') ->from('labels', 'l') ->andWhere($filterSpecs) ->execute() ->fetchAssociative(); $labelData = json_decode($labels['data'], true); // Auto assigned products by filter $this->productLabelUtil->updateProductLabelRelationsByAutoAssignment(1, $labelData); $productLabelRelation = sqlQueryBuilder() ->select('*') ->from('product_labels_relation', 'plr') ->where(Operator::equals(['id_label' => 1])) ->execute() ->fetchAllAssociative(); $this->assertCount(3, $productLabelRelation); $this->assertEquals($manualAssignedItem, $this->getProductByProperty($productLabelRelation, 9410)); $this->assertEquals(1, $this->getProductByProperty($productLabelRelation, 42916)['generated']); // Set filter to nonsense data (to delete generated) $labelData['product_filter']['in_store_range']['max'] = '9000000'; $labelData['product_filter']['in_store_range']['min'] = '8999999'; // Auto delete assigned products $this->productLabelUtil->updateProductLabelRelationsByAutoAssignment(1, $labelData); $productLabelRelation = sqlQueryBuilder() ->select('*') ->from('product_labels_relation', 'plr') ->where(Operator::equals(['id_label' => 1])) ->execute() ->fetchAllAssociative(); $this->assertCount(1, $productLabelRelation); $this->assertEquals($manualAssignedItem, $this->getProductByProperty($productLabelRelation, 9410)); } /** @dataProvider data_testAutomaticLabelAssignmentActivationTypes */ public function testAutomaticLabelAssignmentActivationTypes(int $labelId, array $labelData, ?callable $prepareDataFn, int $expectedAssigmentCount): void { $this->assertEquals(0, $this->getLabelAssigmentCount($labelId)); $filterSpecs = $this->labelFilterSpecs->getSpecs(['active' => true, 'id' => $labelId]); $label = sqlQueryBuilder() ->select('l.id, l.data') ->from('labels', 'l') ->andWhere($filterSpecs) ->execute()->fetchAssociative(); $data = json_decode($label['data'] ?: '', true) ?: []; $data = array_merge($data, $labelData); if ($prepareDataFn) { $prepareDataFn(); } $this->productLabelUtil->updateProductLabelRelationsByAutoAssignment($labelId, $data); $this->assertEquals($expectedAssigmentCount, $this->getLabelAssigmentCount($labelId)); } private function getProductByProperty($array, $id): array { return array_reduce($array, static function ($carry, $item) use ($id) { return $item['id_product'] === $id ? $item : $carry; }, []); } private function getLabelAssigmentCount(int $labelId): int { $result = sqlQueryBuilder() ->select('COUNT(*)') ->from('product_labels_relation', 'plr') ->where(Operator::equals(['plr.id_label' => $labelId])) ->execute()->fetchOne(); return $result ?: 0; } private function data_testAutomaticLabelAssignmentActivationTypes(): array { $activeIntervalFrom = (new \DateTime())->sub(new \DateInterval('P4D'))->format('d.m.Y H:i:s'); $activeIntervalTo = (new \DateTime())->add(new \DateInterval('P4D'))->format('d.m.Y H:i:s'); // labelId, labelData, prepareDataFn, expectedAssigmentCount return [ // typ "na akci" - aktivuje se na produkty, na ktere plati podminka "14 dni od zalozeni produktu" [2, ['active_type' => 'Y', 'active_action_days' => 14, 'active_action_type' => 'from_product_creation'], fn () => $this->prepareData_testAutomaticLabelAssignmentActivationTypes_0(), 1], // typ "na akci" - nic by se nemelo zaradit, protoze nemam zadny produkt, na ktery by platila podminka [2, ['active_type' => 'Y', 'active_action_days' => 14, 'active_action_type' => 'from_product_creation'], fn () => $this->prepareData_testAutomaticLabelAssignmentActivationTypes_1(), 0], // typ "infinite" - melo by se zaradit vsechno zbozi, protoze nemam zadny filtr [2, ['active_type' => 'N'], null, 10], ]; } private function prepareData_testAutomaticLabelAssignmentActivationTypes_0(): void { // vsem produktum nastavim aktualni datum sqlQueryBuilder() ->update('products') ->directValues(['date_added' => (new \DateTime('2022-10-01'))->format('Y-m-d H:i:s')]) ->execute(); // jednomu produktu nastavim datum tak, aby byl starsi jak 14 dnu a tim padem se na nej aplikuje akce "14 dni od vytvoreni produktu" sqlQueryBuilder() ->update('products') ->directValues(['date_added' => (new \DateTime())->format('Y-m-d H:i:s')]) ->where(Operator::equals(['id' => 16])) ->execute(); } private function prepareData_testAutomaticLabelAssignmentActivationTypes_1(): void { // vsem produktum nastavim nejakej starej datum pridani sqlQueryBuilder() ->update('products') ->directValues(['date_added' => (new \DateTime('2022-10-01'))->format('Y-m-d H:i:s')]) ->execute(); } }