Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
TagSeoUpdateJob
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 3
30
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getJobType
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 execute
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2declare(strict_types=1);
3
4namespace App\Job;
5
6use App\Service\Api\AiService;
7use Cake\Queue\Job\Message;
8use Interop\Queue\Processor;
9
10/**
11 * TagSeoUpdateJob
12 *
13 * This job is responsible for updating SEO-related information for tags using AI.
14 * It processes queued messages, retrieves tag information, generates SEO content, and updates the tag record.
15 */
16class TagSeoUpdateJob extends AbstractJob
17{
18    /**
19     * The AI service used for generating SEO content.
20     *
21     * @var \App\Service\Api\AiService
22     */
23    private AiService $aiService;
24
25    /**
26     * Constructor to allow dependency injection for testing.
27     *
28     * @param \App\Service\Api\AiService|null $aiService The AI service instance.
29     */
30    public function __construct(?AiService $aiService = null)
31    {
32        $this->aiService = $aiService ?? new AiService();
33    }
34
35    /**
36     * Get the human-readable job type name for logging
37     *
38     * @return string The job type description
39     */
40    protected static function getJobType(): string
41    {
42        return 'tag SEO update';
43    }
44
45    /**
46     * Executes the job to update tag SEO information.
47     *
48     * This method processes the queued message, retrieves the tag, generates SEO content using AI,
49     * and updates the tag record with the new SEO information.
50     *
51     * @param \Cake\Queue\Job\Message $message The message containing the job data.
52     * @return string|null Returns Processor::ACK on success, Processor::REJECT on failure.
53     */
54    public function execute(Message $message): ?string
55    {
56        if (!$this->validateArguments($message, ['id', 'title'])) {
57            return Processor::REJECT;
58        }
59
60        $id = $message->getArgument('id');
61        $title = $message->getArgument('title');
62
63        $tagsTable = $this->getTable('Tags');
64        $tag = $tagsTable->get($id);
65
66        return $this->executeWithErrorHandling($id, function () use ($tag, $tagsTable, $title) {
67            $seoResult = $this->aiService->generateTagSeo(
68                (string)$title,
69                (string)$tag->description,
70            );
71
72            if ($seoResult) {
73                $emptyFields = $tagsTable->emptySeoFields($tag);
74                array_map(fn($field) => $tag->{$field} = $seoResult[$field], $emptyFields);
75
76                return $tagsTable->save($tag, ['noMessage' => true]);
77            }
78
79            return false;
80        }, $title);
81    }
82}