1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
RequestPreviewImage.php
См. документацию.
1<?php
2declare(strict_types=1);
3
4namespace Bitrix\Landing\Copilot\Generation\Step;
5
6use Bitrix\Landing\Copilot\Connector\AI;
7use Bitrix\Landing\Copilot\Connector\AI\Prompt;
8use Bitrix\Landing\Copilot\Data\Block\Collector;
9use Bitrix\Landing\Copilot\Data\Node\Node;
10use Bitrix\Landing\Copilot\Data\Site;
11use Bitrix\Landing\Copilot\Data\Type\NodeType;
12use Bitrix\Landing\Copilot\Generation\Request;
13use Bitrix\Landing\Copilot\Generation\Type;
14use Bitrix\Landing\Copilot\Generation\Type\RequestEntities;
15use Bitrix\Landing\Copilot\Generation\Type\RequestQuotaDto;
16use Bitrix\Landing\Copilot\Model\RequestToEntitiesTable;
17use Bitrix\Landing\Landing;
18use Bitrix\Landing\Rights;
19
21{
22 public function __construct()
23 {
24 parent::__construct();
25 if (class_exists(self::getConnectorClass()))
26 {
27 $this->connector = new (self::getConnectorClass())();
28 }
29 }
30
34 public static function getConnectorClass(): string
35 {
36 return AI\Image::class;
37 }
38
43 {
44 return new RequestQuotaDto(self::getConnectorClass(), 1);
45 }
46
50 public function isAsync(): bool
51 {
52 return true;
53 }
54
55 protected const EVENT_NAME = 'onPreviewImageCreate';
56
60 protected function getEntityToRequest(): array
61 {
62 if (!isset($this->siteData))
63 {
64 return [];
65 }
66
67 static $entities = null;
68 if (isset($entities))
69 {
70 return $entities;
71 }
72
73 $entities = [];
74
75 $landingId = $this->siteData->getLandingId();
76 $prompt = $this->siteData->getPreviewImagePromptText();
77
78 $entity = [];
79 $key = self::createEntityKey($landingId);
80 $entity[$key] = [
81 'landingId' => $landingId,
82 'prompt' => $prompt,
83 ];
84
85 // mark sent requests
86 if (!empty($entity))
87 {
88 $generationId = $this->generation->getId();
89
90 $res = RequestToEntitiesTable::query()
91 ->setSelect([
92 'REQUEST_ID',
93 'LANDING_ID',
94 ])
95 ->where('LANDING_ID', '=', $landingId)
96 ->where('STEP_REF.GENERATION_ID', '=', $generationId)
97 ->where('STEP_REF.STEP', '=', $this->stepId)
98 ->where('REQUEST_REF.DELETED', '=', 'N')
99 ->exec()
100 ;
101
102 while ($row = $res->fetch())
103 {
104 $key = self::createEntityKey($row['LANDING_ID']);
105 if (isset($entity[$key]))
106 {
107 $entity[$key]['requestId'] = (int)$row['REQUEST_ID'];
108 }
109 }
110 }
111
112 return $entity;
113 }
114
115 protected static function createEntityKey(int $landingId): string
116 {
117 return "l{$landingId}_preview";
118 }
119
120 protected function sendRequest(): bool
121 {
122 if (!isset($this->siteData, $this->stepId))
123 {
124 return false;
125 }
126
127 $entity = $this->getEntityToRequest();
128 if (!isset($entity['landingId'], $entity['prompt']))
129 {
130 return false;
131 }
132
133 if (isset($entity['requestId']))
134 {
135 return false;
136 }
137
138 $prompt = new Prompt($entity['prompt']);
139 $prompt->setMarkers(['format' => 'square']);
140
141 $request = new Request($this->generation->getId(), $this->stepId);
142 if ($request->send($prompt, $this->connector))
143 {
144 RequestToEntitiesTable::add([
145 'REQUEST_ID' => $request->getId(),
146 'ENTITY_TYPE' => Type\RequestEntities::Image->value,
147 'LANDING_ID' => $entity['landingId'],
148 ]);
149 }
150
151 return true;
152 }
153
154 protected function applyResponse(): bool
155 {
156 $responseApplied = false;
157 $previewSrc = null;
158 $isNeedSetPreviewImageSrcToNode = false;
159
160 $this->getEvent()->send(self::EVENT_NAME);
161
162 if (empty($this->request->getError()))
163 {
164 $result = $this->request->getResult();
165
166 if (isset($result[0]))
167 {
168 $previewSrc = $result[0];
169 $isNeedSetPreviewImageSrcToNode = true;
170 }
171
172 $responseApplied = true;
173 }
174
175 if ($responseApplied === false)
176 {
177 $fixedPreview = $this->fixPreview();
178 if ($fixedPreview !== null)
179 {
180 $previewSrc = $fixedPreview;
181 $responseApplied = true;
182 }
183 }
184
185 if ($previewSrc && $previewSrc !== $this->siteData->getPreviewImageSrc())
186 {
187 $this->siteData->setPreviewImageSrc($previewSrc);
188 if ($isNeedSetPreviewImageSrcToNode)
189 {
191 }
192
193 $landingId = $this->siteData->getLandingId();
194 if ($landingId > 0)
195 {
196 $additionalFields = [
197 'METAOG_IMAGE' => $previewSrc,
198 ];
200 Landing::saveAdditionalFields($this->siteData->getLandingId(), $additionalFields);
202 }
203 }
204
205 return $responseApplied;
206 }
207
208 private function fixPreview(): ?string
209 {
210 $fixedPreviewSrc = null;
211 foreach ($this->siteData->getBlocks() as $block)
212 {
213 foreach ($block->getNodes() as $node)
214 {
215 $previewSrc = $this->findSrcInNode($node);
216 if ($previewSrc !== null)
217 {
218 $fixedPreviewSrc = $previewSrc;
219 break 2;
220 }
221 }
222 }
223
224 return $fixedPreviewSrc;
225 }
226
227 private function findSrcInNode(Node $node): ?string
228 {
229 if (
230 $node->getType() !== NodeType::Img
231 || (method_exists($node, 'getGenderData') && !empty($node->getGenderData()))
232 )
233 {
234 return null;
235 }
236
237 $allowedAspectRatios = ['3by2', '16by9'];
238 $sizeData = null;
239 if (method_exists($node, 'getSizeData'))
240 {
241 $sizeData = $node->getSizeData();
242 }
243
244 if ($sizeData !== null)
245 {
246 $position = 0;
247 foreach ($node->getValues() as $value)
248 {
249 if (
250 isset($value['src'], $value['defaultSrc'], $sizeData[$position]['aspectRatio'])
251 && $value['src'] !== $value['defaultSrc']
252 && in_array($sizeData[$position]['aspectRatio'], $allowedAspectRatios, true)
253 )
254 {
255 return $value['src'];
256 }
257 $position++;
258 }
259 }
260
261 return null;
262 }
263
264 protected function getPrompt(): Prompt
265 {
266 $prompt = new Prompt($this->siteData->getPreviewImagePromptText());
267 $prompt->setMarkers(['format' => 'landscape']);
268
269 return $prompt;
270 }
271
277 protected function setPreviewImageSrcToNode(): void
278 {
279 $isFindFirstNode = false;
280 $imgNodesUsesPreviewImage = Collector::getImgNodesUsePreviewImage();
281 foreach ($this->siteData->getBlocks() as $block)
282 {
283 if ($isFindFirstNode)
284 {
285 break;
286 }
287 $codeBlock = $block->getCode();
288 foreach ($block->getNodes() as $node)
289 {
290 $codeNode = $node->getCode();
291 if (
292 isset($imgNodesUsesPreviewImage[$codeBlock])
293 && in_array($codeNode, $imgNodesUsesPreviewImage[$codeBlock])
294 && method_exists($node, 'setImageFromPath')
295 )
296 {
297 //todo: add 2x
298 $previewImageSrc = $this->siteData->getPreviewImageSrc();
299 if ($previewImageSrc === null)
300 {
301 return;
302 }
303
304 $position = 0;
305 $node
306 ->setImageFromPath($previewImageSrc, $position)
307 ->toLanding($position);
308
309 $isFindFirstNode = true;
310 $blockId = $block->getId();
311
312 $requestId = $this->request->getId();
313 $existingRecord = RequestToEntitiesTable::getList([
314 'filter' => [
315 'REQUEST_ID' => $requestId,
316 'ENTITY_TYPE' => RequestEntities::Image->value,
317 'BLOCK_ID' => $blockId,
318 'NODE_CODE' =>$codeNode,
319 'POSITION' => $position,
320 ],
321 ])->fetch();
322
323 if (!$existingRecord)
324 {
325 RequestToEntitiesTable::add([
326 'REQUEST_ID' => $requestId,
327 'ENTITY_TYPE' => RequestEntities::Image->value,
328 'LANDING_ID' => null,
329 'BLOCK_ID' => $blockId,
330 'NODE_CODE' => $codeNode,
331 'POSITION' => 0,
332 ]);
333 }
334
335 //if the block has already been created
336 if ($blockId > 0)
337 {
338 $blockInstance = $this->siteData->getLandingInstance()?->getBlockById($blockId);
339 $blockNodes = $block->getNodes();
340 if ($blockInstance && $blockNodes)
341 {
342 $nodesArray[$codeNode] = $node->getValues();
343 $blockInstance->updateNodes($nodesArray);
344 $blockInstance->save();
345 }
346 }
347 break;
348 }
349 }
350 }
351 }
352
353 public function verifyResponse(): void
354 {
355 }
356}
static saveAdditionalFields(Entity\Event $event)
Определения site.php:1329
static setGlobalOn()
Определения rights.php:116
static setGlobalOff()
Определения rights.php:107
Определения request.php:10
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$res
Определения filter_act.php:7
$result
Определения get_property_values.php:14
$entity
$value
Определения Param.php:39
Определения cookies.php:2
Определения collection.php:2
if(empty($signedUserToken)) $key
Определения quickway.php:257