v1.0.0.0
StocketBase
- <?php
-
- declare(strict_types=1);
-
- require_once __DIR__ . '/database.php';
- require_once __DIR__ . '/slugger.php';
-
- final class ProductTags
- {
- public const MAX_TAGS = 10;
- public const NAME_MAX = 60;
-
- private static ?bool $enabled = null;
-
- public static function isEnabled(): bool
- {
- if (self::$enabled !== null) {
- return self::$enabled;
- }
-
- try {
- $statement = Database::site()->prepare('SELECT setting_value FROM site_settings WHERE setting_key = :key LIMIT 1');
- $statement->execute(['key' => 'tags_enabled']);
- self::$enabled = $statement->fetchColumn() === '1';
- } catch (PDOException $e) {
- self::$enabled = false;
- }
-
- return self::$enabled;
- }
-
- public static function parse(string $input): array
- {
- $names = [];
- $seen = [];
-
- foreach (preg_split('/[,;\n]+/', $input) ?: [] as $raw) {
- $name = strip_tags($raw);
- $name = (string) preg_replace('/[\x00-\x1F\x7F]+/u', ' ', $name);
- $name = trim((string) preg_replace('/\s+/u', ' ', $name));
- $name = mb_substr($name, 0, self::NAME_MAX);
-
- $key = mb_strtolower($name);
- if ($name === '' || isset($seen[$key])) {
- continue;
- }
-
- $seen[$key] = true;
- $names[] = $name;
-
- if (count($names) >= self::MAX_TAGS) {
- break;
- }
- }
-
- return $names;
- }
-
- public static function slugFor(string $name): string
- {
- $slug = substr(Slugger::make($name), 0, 80);
-
- return $slug !== '' ? $slug : 'tag-' . substr(sha1(mb_strtolower($name)), 0, 8);
- }
-
- public static function sync(int $productId, array $names): void
- {
- $db = Database::site();
-
- try {
- $db->beginTransaction();
-
- $upsert = $db->prepare('INSERT INTO tags (name, slug) VALUES (:name, :slug) ON DUPLICATE KEY UPDATE id = LAST_INSERT_ID(id)');
- $tagIds = [];
- foreach ($names as $name) {
- $upsert->execute(['name' => $name, 'slug' => self::slugFor($name)]);
- $tagIds[] = (int) $db->lastInsertId();
- }
-
- $db->prepare('DELETE FROM product_tags WHERE product_id = :id')->execute(['id' => $productId]);
-
- $link = $db->prepare('INSERT IGNORE INTO product_tags (product_id, tag_id) VALUES (:product, :tag)');
- foreach (array_unique($tagIds) as $tagId) {
- $link->execute(['product' => $productId, 'tag' => $tagId]);
- }
-
- $db->exec('DELETE FROM tags WHERE id NOT IN (SELECT tag_id FROM product_tags)');
-
- $db->commit();
- } catch (PDOException $e) {
- if ($db->inTransaction()) {
- $db->rollBack();
- }
- error_log('StocketBase: could not save tags: ' . $e->getMessage());
- }
- }
-
- public static function forProduct(int $productId): array
- {
- try {
- $statement = Database::site()->prepare(
- 'SELECT t.name, t.slug FROM tags t JOIN product_tags l ON l.tag_id = t.id WHERE l.product_id = :id ORDER BY t.name ASC'
- );
- $statement->execute(['id' => $productId]);
-
- return $statement->fetchAll();
- } catch (PDOException $e) {
- return [];
- }
- }
-
- public static function csvFor(int $productId): string
- {
- return implode(', ', array_column(self::forProduct($productId), 'name'));
- }
-
- public static function findBySlug(string $slug): ?array
- {
- if (preg_match('/^[a-z0-9-]{1,80}$/', $slug) !== 1) {
- return null;
- }
-
- $statement = Database::site()->prepare('SELECT id, name, slug FROM tags WHERE slug = :slug LIMIT 1');
- $statement->execute(['slug' => $slug]);
-
- return $statement->fetch() ?: null;
- }
- }
-