Skip to content

Commit

Permalink
Merge pull request #34 from ittweb/dev
Browse files Browse the repository at this point in the history
Changed image handling
  • Loading branch information
marco-zanella committed Aug 30, 2021
2 parents f3f9ceb + 7767a23 commit 365d612
Show file tree
Hide file tree
Showing 20 changed files with 284 additions and 75 deletions.
18 changes: 7 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -196,27 +196,23 @@ Categories are not explicitly handled by the `CollectorFacade`, which will trans

### Adding Image Information

Information about pictures of a product are handled by the `ImageInfo` class, which allows to specify a primary (main) image, a secondary (over) image an a list of other images:
Information about pictures of a product are handled by the `Image` class which allows to specify, for each image, a label, an URL and a position:

```php
use \AccelaSearch\ProductMapper\ImageInfo;

$image_info = new ImageInfo();
$image_info->setMain("http://www.myshop.com/storage/images/001.jpeg")
->setOver("http://www.myshop.com/storage/secondary/001a.jpeg")
->addOther("http://www.myshop.com/storage/secondary/001b.jpeg")
->addOther("http://www.myshop.com/storage/secondary/001c.jpeg")
->addOther("http://www.myshop.com/storage/secondary/001e.jpeg");
use \AccelaSearch\ProductMapper\Image;

$image_1 = new Image("main", "http://www.myshop.com/storage/images/001.jpeg", 1);
$image_2 = new Image("over", "http://www.myshop.com/storage/images/002.jpeg", 3);
```

When creating products through the `ProductFactory`, an empty `ImageInfo` is automatically instantiated upon creation, and may be accessed through its accessors methods:
Images can be added to items through the `addImage` method:

```php
use \AccelaSearch\ProductMapper\ProductFactory;

$factory = new ProductFactory();
$item = $factory->createSimple("http://myshop.com/SIMPLE0001", "SIMPLE0001");
$item->getImageInfo()->setMain("http://myshop.com/storage/images/simple0001.jpeg");
$item->addImage($image_1)->addImage($image_2);
```

### Adding Availability
Expand Down
Binary file modified doc/class-diagram.dia
Binary file not shown.
Binary file modified doc/collector-schema.dia
Binary file not shown.
5 changes: 2 additions & 3 deletions src/Bundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ public function __construct(
string $url,
string $external_identifier,
Availability $availability,
Pricing $pricing,
ImageInfo $image_info
Pricing $pricing
) {
$this->identifier = null;
$this->sku = null;
Expand All @@ -21,7 +20,7 @@ public function __construct(
$this->pricing = $pricing;
$this->external_identifier = $external_identifier;
$this->categories = [];
$this->image_info = $image_info;
$this->images = [];
$this->attributes = [];
$this->products = [];
}
Expand Down
5 changes: 2 additions & 3 deletions src/Configurable.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ public function __construct(
string $url,
string $external_identifier,
Availability $availability,
Pricing $pricing,
ImageInfo $image_info
Pricing $pricing
) {
$this->identifier = null;
$this->sku = null;
Expand All @@ -21,7 +20,7 @@ public function __construct(
$this->pricing = $pricing;
$this->external_identifier = $external_identifier;
$this->categories = [];
$this->image_info = $image_info;
$this->images = [];
$this->attributes = [];
$this->variants = [];
}
Expand Down
14 changes: 9 additions & 5 deletions src/Converter/Dictionary/Visitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,15 @@ private function product($item): array {
'sku' => $item->getSku(),
'url' => $item->getUrl()
],
'image' => [
'main' => $item->getImageInfo()->getMain(),
'over' => $item->getImageInfo()->getMain(),
'other' => $item->getOtherAsArray()
],
'image' => array_map(function ($image) {
return [
'label' => $image->getLabel(),
'url' => $image->getUrl(),
'position' => $image->getPosition()
];
},
$item->getImagesAsArray()
),
'categories' => $this->categories($item->getCategoriesAsArray()),
'data' => $this->attributes($item->getAttributesAsArray()),
'availability' => $this->availability($item->getAvailability()),
Expand Down
57 changes: 57 additions & 0 deletions src/DataMapper/Sql/ImageLabel.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php
namespace AccelaSearch\ProductMapper\DataMapper\Sql;
use \OutOfBoundsException;
use \AccelaSearch\ProductMapper\ImageLabel as Subject;

class ImageLabel {
private $connection;

public function __construct(Connection $connection) {
$this->connection = $connection;
}

public static function fromConnection(Connection $connection): self {
return new ImageLabel($connection);
}

public function create(Subject $image_label): self {
$query = 'INSERT INTO products_images_lbl(label, storeviewid, deleted) VALUES(:label, :shop_identifier, 0)';
$sth = $this->connection->getDbh()->prepare($query);
$sth->execute([
':label' => $image_label->getLabel(),
':shop_identifier' => $this->connection->getShopIdentifier(),
]);
$image_label->setIdentifier($this->connection->getDbh()->lastInsertId());
return $this;
}

public function read(int $identifier): Subject {
$query = 'SELECT id, label, deleted FROM products_images_lbl WHERE id = :identifier';
$sth = $this->connection->getDbh()->prepare($query);
$sth->execute([':identifier' => $identifier]);
$row = $sth->fetch();
if (empty($row)) {
throw new OutOfBoundsException('No image label with identifier ' . $identifier);
}
return $this->rowToImageLabel($row);
}

public function search(): array {
$query = 'SELECT id, label, deleted FROM products_images_lbl WHERE storeviewid = :shop_identifier';
$sth = $this->connection->getDbh()->prepare($query);
$sth->execute([':shop_identifier' => $this->connection->getShopIdentifier()]);
$labels = [];
while ($row = $sth->fetch()) {
$labels[] = $this->rowToImageLabel($row);
}
return $labels;
}

private function rowToImageLabel(array $row): Subject {
return new Subject(
$row['id'],
$row['label'],
$row['deleted'] == 0
);
}
}
47 changes: 30 additions & 17 deletions src/DataMapper/Sql/Item.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@
use \AccelaSearch\ProductMapper\ProductInterface;
use \AccelaSearch\ProductMapper\StockableInterface;
use \AccelaSearch\ProductMapper\SellableInterface;
use \AccelaSearch\ProductMapper\ImageLabel;
use \AccelaSearch\ProductMapper\DataMapper\ItemInterface as ItemMapperInterface;

class Item implements ItemMapperInterface {
private $connection;
private $attribute_lookup;
private $image_label_lookup;
private $image_label_mapper;
private $item_reader;
private $item_get_type;
private $item_is_product;
Expand All @@ -18,21 +21,25 @@ class Item implements ItemMapperInterface {

public function __construct(
Connection $connection,
ImageLabel $image_label_mapper,
ItemReader $item_reader,
ItemGetTypeVisitor $item_get_type,
ItemIsProductVisitor $item_is_product,
ItemGetChildrenVisitor $item_get_children,
QuantityConverterVisitor $quantity_converter
) {
$this->connection = $connection;
$this->attribute_lookup = [];
$this->image_label_lookup = [];
$this->image_label_mapper = $image_label_mapper;
$this->item_reader = $item_reader;
$this->item_get_type = $item_get_type;
$this->item_is_product = $item_is_product;
$this->attribute_lookup = [];
$this->item_get_children = $item_get_children;
$this->quantity_converter = $quantity_converter;

$this->initializeAttributeLookup();
$this->initializeImageLabelLookup();
}

public static function fromConnection(Connection $connection): self {
Expand Down Expand Up @@ -100,7 +107,7 @@ public function create(ItemInterface $item): ItemMapperInterface {
}
$this->insertAttributes($item);
$this->insertCategories($item);
$this->insertImageInfo($item);
$this->insertImages($item);
$this->insertAvailability($item);
$this->insertPricing($item);
}
Expand Down Expand Up @@ -176,6 +183,13 @@ private function initializeAttributeLookup(): self {
return $this;
}

private function initializeImageLabelLookup(): self {
foreach ($this->image_label_mapper->search() as $image_label) {
$this->image_label_lookup[$image_label->getLabel()] = $image_label->getIdentifier();
}
return $this;
}

private function insertAttributes(ProductInterface $item): self {
$clauses = [];
$binders = [];
Expand Down Expand Up @@ -234,34 +248,33 @@ private function insertCategories(ProductInterface $item): self {
return $this;
}

private function insertImageInfo(ProductInterface $item): self {
private function insertImages(ProductInterface $item): self {
$clauses = [];
$binders = [];
$push = function (string $url, bool $is_main, bool $is_over) use($item, &$clauses, &$binders) {
$push = function (string $url, int $label_identifier, int $position) use($item, &$clauses, &$binders) {
$progressive_identifier = count($clauses) + 1;
$clauses[] = '(:product_identifier_' . $progressive_identifier
. ', :product_external_identifier_' . $progressive_identifier
. ', :is_main_' . $progressive_identifier
. ', :is_over_' . $progressive_identifier
. ', :label_identifier_' . $progressive_identifier
. ', :sort_' . $progressive_identifier
. ', :url_' . $progressive_identifier . ')'
;
$binders[':product_identifier_' . $progressive_identifier] = $item->getIdentifier();
$binders[':product_external_identifier_' . $progressive_identifier] = $item->getExternalIdentifier();
$binders[':is_main_' . $progressive_identifier] = $is_main ? 1 : 0;
$binders[':is_over_' . $progressive_identifier] = $is_over ? 1 : 0;
$binders[':label_identifier_' . $progressive_identifier] = $label_identifier;
$binders[':sort_' . $progressive_identifier] = $position;
$binders[':url_' . $progressive_identifier] = $url;
};
if (!is_null($item->getImageInfo()->getMain())) {
$push($item->getImageInfo()->getMain(), true, false);
}
if (!is_null($item->getImageInfo()->getOver())) {
$push($item->getImageInfo()->getOver(), false, true);
}
foreach ($item->getImageInfo()->getOtherAsArray() as $other) {
$push($other, false, false);
foreach ($item->getImagesAsArray() as $image) {
if (!isset($this->image_label_lookup[$image->getLabel()])) {
$image_label = new ImageLabel(null, $image->getLabel(), true);
$this->image_label_mapper->create($image_label);
$this->image_label_lookup[$image->getLabel()] = $image_label->getIdentifier();
}
$push($image->getUrl(), $this->image_label_lookup[$image->getLabel()], $image->getPosition());
}
if (!empty($clauses)) {
$query = 'INSERT INTO products_images(productid, externalproductidstr, main, `over`, url) VALUES '
$query = 'INSERT INTO products_images(productid, externalproductidstr, labelid, sort, url) VALUES '
. implode(', ', $clauses);
$sth = $this->connection->getDbh()->prepare($query);
$sth->execute($binders);
Expand Down
18 changes: 6 additions & 12 deletions src/DataMapper/Sql/ItemReader.php
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ private function searchChildrenByIdentifier(int $identifier): array {
private function buildProduct(ProductInterface $item): self {
return $this->buildAttributes($item)
->buildCategories($item)
->buildImageInfo($item)
->buildImages($item)
->buildPricing($item)
->buildAvailability($item)
;
Expand Down Expand Up @@ -197,20 +197,14 @@ private function buildCategories(ProductInterface $item): self {
return $this;
}

private function buildImageInfo(ProductInterface $item): self {
$query = 'SELECT main, `over`, url FROM products_images WHERE productid = :identifier AND deleted = 0';
private function buildImages(ProductInterface $item): self {
$query = 'SELECT label, sort, url FROM products_images JOIN products_images_lbl '
. 'ON products_images.labelid = products_images_lbl.id '
. 'WHERE productid = :identifier AND products_images.deleted = 0 AND products_images_lbl.deleted = 0';
$sth = $this->connection->getDbh()->prepare($query);
$sth->execute([':identifier' => $item->getIdentifier()]);
while ($row = $sth->fetch()) {
if ($row['main'] == 1) {
$item->getImageInfo()->setMain($row['url']);
}
elseif ($row['over'] == 1) {
$item->getImageInfo()->setOver($row['url']);
}
else {
$item->getImageInfo()->addOther($row['url']);
}
$item->addImage(new Image($row['label'], $row['url'], $row['position']));
}
return $this;
}
Expand Down
5 changes: 2 additions & 3 deletions src/Downloadable.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@ public function __construct(
string $url,
string $external_identifier,
Availability $availability,
Pricing $pricing,
ImageInfo $image_info
Pricing $pricing
) {
parent::__construct($url, $external_identifier, $availability, $pricing, $image_info);
parent::__construct($url, $external_identifier, $availability, $pricing);
}

public function accept(VisitorInterface $visitor) {
Expand Down
5 changes: 2 additions & 3 deletions src/Grouped.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@ public function __construct(
string $url,
string $external_identifier,
Availability $availability,
Pricing $pricing,
ImageInfo $image_info
Pricing $pricing
) {
parent::__construct($url, $external_identifier, $availability, $pricing, $image_info);
parent::__construct($url, $external_identifier, $availability, $pricing);
}

public function accept(VisitorInterface $visitor) {
Expand Down
45 changes: 45 additions & 0 deletions src/Image.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php
namespace AccelaSearch\ProductMapper;

class Image {
private $label;
private $url;
private $position;

public function __construct(
string $label,
string $url,
int $position
) {
$this->label = $label;
$this->url = $url;
$this->position = $position;
}

public function getLabel(): ?string {
return $this->label;
}

public function setLabel(string $label): self {
$this->label = $label;
return $this;
}

public function getUrl(): string {
return $this->url;
}

public function setUrl(string $url): self {
$this->url = $url;
return $this;
}

public function getPosition(): int {
return $this->position;
}

public function setPosition(int $position): self {
$this->position = $position;
return $this;
}
}
Loading

0 comments on commit 365d612

Please sign in to comment.