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
ArticleSeoUpdateJob
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 * ArticleSeoUpdateJob
12 *
13 * This job is responsible for updating the SEO metadata of an article using AI.
14 * It processes messages from the queue to update various SEO-related fields of an article.
15 */
16class ArticleSeoUpdateJob extends AbstractJob
17{
18    /**
19     * Instance of the AI service.
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
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 'article SEO update';
43    }
44
45    /**
46     * Executes the job to update article SEO metadata.
47     *
48     * @param \Cake\Queue\Job\Message $message The message containing article data
49     * @return string|null Returns Processor::ACK on success, Processor::REJECT on failure
50     */
51    public function execute(Message $message): ?string
52    {
53        $id = $message->getArgument('id');
54        $title = $message->getArgument('title');
55
56        if (!$this->validateArguments($message, ['id', 'title'])) {
57            return Processor::REJECT;
58        }
59
60        return $this->executeWithErrorHandling($id, function () use ($id, $title) {
61            $articlesTable = $this->getTable('Articles');
62            $article = $articlesTable->get($id);
63
64            $seoResult = $this->aiService->generateArticleSeo(
65                (string)$title,
66                (string)strip_tags($article->body),
67            );
68
69            if ($seoResult) {
70                $emptyFields = $articlesTable->emptySeoFields($article);
71                array_map(fn($field) => $article->{$field} = $seoResult[$field], $emptyFields);
72
73                return $articlesTable->save($article, ['noMessage' => true]);
74            }
75
76            return false;
77        }, $title);
78    }
79}