1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
attachmenthelper.php
См. документацию.
1<?php
2
3namespace Bitrix\Mail\Helper;
4
5use Bitrix\Mail\Internals\MailboxDirectoryTable;
6use Bitrix\Mail\Internals\MailMessageAttachmentTable;
7use Bitrix\Mail\MailboxTable;
8use Bitrix\Mail\MailMessageTable;
9use Bitrix\Mail\MailMessageUidTable;
10use Bitrix\Mail\Imap;
11use Bitrix\Main\Error;
12use Bitrix\Main\Result;
13use Bitrix\Main\Web\MimeType;
14
16{
17 public function __construct(
18 public ?string $name,
19 public ?int $size,
20 public ?string $type,
21 public ?string $content = null,
22 public ?int $diskId = null,
23 public ?int $imageWidth = null,
24 public ?int $imageHeight = null,
25 public ?string $contentId = null,
26 public ?int $attachmentId = null,
27 )
28 {}
29}
30
32{
33 public function __construct(
34 public int $mailboxId,
35 public string $dirPath,
36 public string $uid,
37 public int $id,
38 public ?int $attachmentsCount = null,
39 public ?string $body = null,
40 )
41 {}
42}
43
45{
46 private const MESSAGE_PARTS_TEXT = 1;
47 private const MESSAGE_PARTS_ATTACHMENT = 2;
48 private const MESSAGE_PARTS_ALL = -1;
49
50 private const COMPARISON_ATTACHMENT_LEVEL_STRONG = 2;
51 private const COMPARISON_ATTACHMENT_LEVEL_AVERAGE = 1;
52 private const COMPARISON_ATTACHMENT_LEVEL_LOW = 0;
53
54 private const MAILBOX_ENCODING = 'UTF-8';
55
56 private ?Imap $client;
57 private ?MessageStructure $message = null;
58
59 private function getImapClient(int $mailboxId): ?Imap
60 {
61 $mailbox = MailboxTable::getRow([
62 'select' => [
63 'SERVER',
64 'PORT',
65 'USE_TLS',
66 'LOGIN',
67 'PASSWORD',
68 ],
69 'filter' => [
70 '=ID' => $mailboxId,
71 '=ACTIVE' => 'Y',
72 ],
73 ]);
74
75 if (is_null($mailbox))
76 {
77 return null;
78 }
79
80 $mailboxTls = $mailbox['USE_TLS'];
81
82 return new Imap(
83 $mailbox['SERVER'],
84 (int) $mailbox['PORT'],
85 ($mailboxTls === 'Y' || $mailboxTls === 'S'),
86 ($mailboxTls === 'Y'),
87 $mailbox['LOGIN'],
88 $mailbox['PASSWORD'],
89 'UTF-8'
90 );
91 }
92
93 public static function generateMessageAttachmentPath(): string
94 {
95 return 'mail/message_attachment/'.date('Y-m-d');
96 }
97
98 public function __construct(int $mailboxId, int $messageId = null, int $messageUid = null)
99 {
101 $mailboxId,
102 [
103 'MSG_UID',
104 'MESSAGE_ID',
105 'DIR_MD5',
106 ],
108 $messageUid,
109 );
110
111 if (!is_null($message))
112 {
113 $dir = MailboxDirectoryTable::getRow([
114 'select' => [
115 'ID',
116 'PATH',
117 ],
118 'filter' => [
119 '=DIR_MD5' => $message['DIR_MD5'],
120 '=MAILBOX_ID' => $mailboxId,
121 ],
122 ]);
123
124 if (!is_null($dir))
125 {
126 $this->message = new MessageStructure($mailboxId, $dir['PATH'], $message['MSG_UID'], (int) $message['MESSAGE_ID']);
127 }
128 }
129
130 $this->client = $this->getImapClient($mailboxId);
131 }
132
133 private function downloadBodyStructure(MessageStructure $messageStructure): ?Imap\BodyStructure
134 {
135 $error = [];
136 $structure = $this->client->fetch(true, $messageStructure->dirPath, $messageStructure->uid, '(BODYSTRUCTURE)', $error);
137
138 if ($error || empty($structure))
139 {
140 return null;
141 }
142
143 return new Imap\BodyStructure($structure['BODYSTRUCTURE']);
144 }
145
146 public static function generateFileName(int $mailboxId, int $messageId, int $attachmentIndex, ?string $attachmentType): string
147 {
148 $fileName = $mailboxId . '-' . $messageId . '-' . $attachmentIndex;
149
150 // @TODO: replace with "\Bitrix\Main\Web\MimeType::getExtensionByMimeType" when it comes out
151 $extension = array_search($attachmentType, MimeType::getMimeTypeList(), true);
152
153 if ($extension)
154 {
155 $fileName .= '.' . $extension;
156 }
157
158 return $fileName;
159 }
160
165 private function downloadAttachments(MessageStructure $messageStructure): array
166 {
167 $attachments = [];
168 $bodyStructure = $this->downloadBodyStructure($messageStructure);
169
170 if (is_null($bodyStructure))
171 {
172 return $attachments;
173 }
174
175 $parts = $this->downloadMessageParts($messageStructure->dirPath, $messageStructure->uid, $bodyStructure, self::MESSAGE_PARTS_ATTACHMENT);
176
177 $bodyStructure->traverse(
178 function (Imap\BodyStructure $item) use (&$parts, &$attachments, $messageStructure)
179 {
180 static $attachmentIndex = 0;
181
182 if ($item->isMultipart() || $item->isBodyText())
183 {
184 return;
185 }
186
187 $attachmentIndex++;
188
191 $parts[sprintf('BODY[%s.MIME]', $item->getNumber())],
192 self::MAILBOX_ENCODING,
193 ),
194 $parts[sprintf('BODY[%s]', $item->getNumber())],
195 self::MAILBOX_ENCODING,
196 );
197
198 $fileName = $attachment['FILENAME'];
199
200 if (is_null($fileName))
201 {
202 $fileName = self::generateFileName($messageStructure->mailboxId, $messageStructure->id, $attachmentIndex, $attachment['CONTENT-TYPE']);
203 }
204
205 $attachments[] = new AttachmentStructure(
206 $fileName,
207 strlen($attachment['BODY']),
208 mb_strtolower($attachment['CONTENT-TYPE']),
209 $attachment['BODY'],
210 contentId: $attachment['CONTENT-ID'],
211 );
212 }
213 );
214
215 return $attachments;
216 }
217
218 private function saveAttachmentToDisk(AttachmentStructure $attachment): ?AttachmentStructure
219 {
220 if (empty($attachment->name))
221 {
222 return null;
223 }
224
225 $fileId = \CFile::saveFile(
226 [
227 'name' => md5($attachment->name),
228 'size' => $attachment->size,
229 'type' => $attachment->type,
230 'content' => $attachment->content,
231 'MODULE_ID' => 'mail'
232 ],
233 self::generateMessageAttachmentPath(),
234 );
235
236 if (!is_int($fileId))
237 {
238 return null;
239 }
240
241 $extendedAttachment = clone $attachment;
242 $extendedAttachment->diskId = $fileId;
243
244 if (is_null($extendedAttachment->imageWidth) && is_null($extendedAttachment->imageHeight))
245 {
246 $file = \CFile::GetFileArray($fileId);
247
248 if (is_set($file['WIDTH']))
249 {
250 $extendedAttachment->imageWidth = (int) $file['WIDTH'];
251 }
252
253 if (is_set($file['HEIGHT']))
254 {
255 $extendedAttachment->imageHeight = (int) $file['HEIGHT'];
256 }
257
258 }
259
260 return $extendedAttachment;
261 }
262
268 public function saveAttachmentsToDisk(array $attachments, bool $abortOnAnError = false): Result
269 {
270 $allResult = new Result();
271 $data = [];
272
274 foreach ($attachments as $attachment)
275 {
276 $extendedAttachment = $this->saveAttachmentToDisk($attachment);
277 if (!is_null($extendedAttachment))
278 {
279 $data[] = $extendedAttachment;
280 }
281 else if ($abortOnAnError)
282 {
283 $allResult->addError(new Error('File upload error', 'FILE_UPLOAD_ERROR'));
284 $allResult->setData($data);
285 return $allResult;
286 }
287 }
288
289 $allResult->setData($data);
290
291 return $allResult;
292 }
293
298 private function getSynchronized(MessageStructure $messageStructure) : array
299 {
300 $attachments = [];
301
302 if (empty($messageStructure->attachmentsCount))
303 {
304 return $attachments;
305 }
306
307 $list = MailMessageAttachmentTable::getList([
308 'select' => [
309 'ID',
310 'FILE_ID',
311 'FILE_NAME',
312 'FILE_SIZE',
313 'CONTENT_TYPE',
314 'IMAGE_WIDTH',
315 'IMAGE_HEIGHT',
316 ],
317 'filter' => [
318 '=MESSAGE_ID' => $messageStructure->id,
319 ],
320 ]);
321
322 while ($item = $list->fetch())
323 {
324 $attachments[] = new AttachmentStructure(
325 $item['FILE_NAME'],
326 $item['FILE_SIZE'],
327 $item['CONTENT_TYPE'],
328 null,
329 $item['FILE_ID'],
330 $item['IMAGE_WIDTH'],
331 $item['IMAGE_HEIGHT'],
332 attachmentId: $item['ID'],
333 );
334 }
335
336 return $attachments;
337 }
338
344 private function deleteAttachedFromDB(MessageStructure $messageStructure, array $attachments) : void
345 {
346 $ids = [];
347
349 foreach ($attachments as $attachment)
350 {
351 $ids[] = $attachment->attachmentId;
352 }
353
354 if ($messageStructure->attachmentsCount > 0)
355 {
356 $messageId = $messageStructure->id;
357
358 if ($messageId > 0 && count($ids) > 0)
359 {
360 MailMessageAttachmentTable::deleteByIds($messageId, $ids);
361 }
362 }
363 }
364
370 private function saveAttachmentsToDB(MessageStructure $messageStructure, array $attachments): array
371 {
372 $newAttachments = [];
373
375 foreach ($attachments as $attachment)
376 {
377 if (!is_null($attachment->diskId))
378 {
379 $result = MailMessageAttachmentTable::add(
380 [
381 'MESSAGE_ID' => $messageStructure->id,
382 'FILE_ID' => $attachment->diskId,
383 'FILE_NAME' => $attachment->name,
384 'FILE_SIZE' => $attachment->size,
385 'FILE_DATA' => null,
386 'CONTENT_TYPE' => $attachment->type,
387 'IMAGE_WIDTH' => $attachment->imageWidth,
388 'IMAGE_HEIGHT' => $attachment->imageHeight,
389 ]
390 );
391
392 $primary = $result->getPrimary();
393
394 if (isset($primary['ID']))
395 {
396 $newAttachment = clone $attachment;
397 $newAttachment->attachmentId = $primary['ID'];
398 $newAttachments[] = $newAttachment;
399 }
400 }
401 }
402
403 return $newAttachments;
404 }
405
406 private function createMessageWithBody(MessageStructure $messageStructure): MessageStructure
407 {
408 $extendedStructure = clone $messageStructure;
409
410 $modelRow = MailMessageTable::getRow([
411 'select' => [
412 'BODY_HTML'
413 ],
414 'filter' => [
415 'ID' => $messageStructure->id,
416 ],
417 ]);
418
419 if (
420 isset($modelRow['BODY_HTML']) &&
421 is_string($modelRow['BODY_HTML'])
422 )
423 {
424 $extendedStructure->body = $modelRow['BODY_HTML'];
425 }
426
427 return $extendedStructure;
428 }
429
430 public function extractFileIdsFromMessageBody(MessageStructure $messageStructure): array
431 {
432 $attachmentIds = [];
433
434 $body = $messageStructure->body;
435
436 if (is_null($body))
437 {
438 return $attachmentIds;
439 }
440
441 $pattern = '/<img[^>]+src\s*=\s*(\'|\")?aid:(?P<id>\d+)\s*\1[^>]*>/is';
442
443 if (preg_match_all($pattern, $body, $matches) !== false)
444 {
445 $attachmentIds = array_map('intval', $matches['id']);
446 }
447
448 return $attachmentIds;
449 }
450
456 private function getAttachmentStructuresByIds(MessageStructure $messageStructure, array $attachmentIds): array
457 {
458 $attachments = [];
459
460 if (count($attachmentIds) === 0)
461 {
462 return $attachments;
463 }
464
465 $attachmentList = MailMessageAttachmentTable::getList([
466 'select' => [
467 'ID',
468 'FILE_NAME',
469 'FILE_SIZE',
470 'FILE_ID',
471 'CONTENT_TYPE',
472 'IMAGE_WIDTH',
473 'IMAGE_HEIGHT',
474 ],
475 'filter' => [
476 '@ID' => $attachmentIds,
477 '=MESSAGE_ID' => $messageStructure->id,
478 ],
479 ]);
480
481 while ($attachment = $attachmentList->fetch())
482 {
483 $attachments[] = new AttachmentStructure(
484 $attachment['FILE_NAME'],
485 $attachment['FILE_SIZE'],
486 $attachment['CONTENT_TYPE'],
487 diskId: (int) $attachment['FILE_ID'],
488 imageWidth: (int) $attachment['IMAGE_WIDTH'],
489 imageHeight: (int) $attachment['IMAGE_HEIGHT'],
490 attachmentId: (int) $attachment['ID']
491 );
492 }
493
494 return $attachments;
495 }
496
501 private function getAttachmentsEmbeddedInMessageBody(MessageStructure $messageStructure) : array
502 {
503 $attachments = [];
504
505 $fileIds = $this->extractFileIdsFromMessageBody($messageStructure);
506
507 if (!empty($fileIds))
508 {
509 $attachments = $this->getAttachmentStructuresByIds($messageStructure, $fileIds);
510 }
511
512 return $attachments;
513 }
514
515 private static function compareAttachment(AttachmentStructure $brokenAttachment, AttachmentStructure $fullAttachment, int $comparisonLevel = self::COMPARISON_ATTACHMENT_LEVEL_STRONG, bool $attachmentIsPicture = true): bool
516 {
517 if ($attachmentIsPicture && !\CFile::isImage($fullAttachment->name, $fullAttachment->type))
518 {
519 return false;
520 }
521
522 if (
523 $comparisonLevel === self::COMPARISON_ATTACHMENT_LEVEL_STRONG &&
524 $brokenAttachment->name === $fullAttachment->name &&
525 $brokenAttachment->type === $fullAttachment->type
526 )
527 {
528 return true;
529 }
530
531 if (
532 $comparisonLevel === self::COMPARISON_ATTACHMENT_LEVEL_AVERAGE &&
533 $brokenAttachment->name === $fullAttachment->name &&
534 $brokenAttachment->size === $fullAttachment->size
535 )
536 {
537 return true;
538 }
539
540 if (
541 $comparisonLevel === self::COMPARISON_ATTACHMENT_LEVEL_LOW &&
542 $brokenAttachment->name === $fullAttachment->name
543 )
544 {
545 return true;
546 }
547
548 return false;
549 }
550
557 private function createMessageWithReplacedAttachmentsInBody(MessageStructure $messageStructure, array $oldAttachments, array $newAttachments) : MessageStructure
558 {
559 $extendedStructure = clone $messageStructure;
560
561 foreach ([
562 self::COMPARISON_ATTACHMENT_LEVEL_STRONG,
563 self::COMPARISON_ATTACHMENT_LEVEL_AVERAGE,
564 self::COMPARISON_ATTACHMENT_LEVEL_LOW
565 ] as $level)
566 {
567 $remainingOldAttachments = [];
568 $remainingNewAttachments = $newAttachments;
569
571 foreach ($oldAttachments as $oldAttachment)
572 {
573 $found = false;
574
576 foreach ($remainingNewAttachments as $newKey => $newAttachment)
577 {
578 if ($this->compareAttachment($oldAttachment, $newAttachment, $level))
579 {
580 $oldId = $oldAttachment->attachmentId;
581 $newId = $newAttachment->attachmentId;
582
583 if ($oldId !== null && $newId !== null && !is_null($extendedStructure->body))
584 {
585 $pattern = '/(src\s*=\s*["\']?aid:)' . $oldId . '(["\']?)/i';
586 $replacement = 'src="aid:'.$newId.'"';
587 $newBody = preg_replace($pattern, $replacement, $extendedStructure->body);
588
589 if (!is_null($newBody))
590 {
591 $extendedStructure->body = $newBody;
592 }
593
594 unset($remainingNewAttachments[$newKey]);
595 $found = true;
596 break;
597 }
598 }
599 }
600
601 if (!$found)
602 {
603 $remainingOldAttachments[] = $oldAttachment;
604 }
605 }
606
607 $oldAttachments = $remainingOldAttachments;
608 $newAttachments = $remainingNewAttachments;
609 }
610
611 return $extendedStructure;
612 }
613
614 public function update(): bool
615 {
616 if (is_null($this->message) || is_null($this->client))
617 {
618 return false;
619 }
620
621 $attachmentStructures = $this->downloadAttachments($this->message);
622 $savingToDiskResult = $this->saveAttachmentsToDisk($attachmentStructures, true);
623 $attachmentStructures = $savingToDiskResult->getData();
624
625 if ($savingToDiskResult->isSuccess() === false)
626 {
628 foreach ($attachmentStructures as $attachment)
629 {
630 if (is_int($attachment->diskId))
631 {
632 \CFile::Delete($attachment->diskId);
633 }
634 }
635
636 return false;
637 }
638
639 $this->message = $this->createMessageWithAttachmentCount($this->message);
640
641 $oldAttachments = $this->getSynchronized($this->message);
642
644 foreach ($oldAttachments as $attachment)
645 {
646 $diskId = $attachment->diskId;
647
648 if (is_int($diskId))
649 {
650 \CFile::Delete($diskId);
651 }
652 }
653
654 $newAttachments = $savingToDiskResult->getData();
655 $newAttachments = $this->saveAttachmentsToDB($this->message, $newAttachments);
656
657 $this->message = $this->createMessageWithBody($this->message);
658
659 $attachmentsEmbeddedInMessageBody = $this->getAttachmentsEmbeddedInMessageBody($this->message);
660
661 $messageWithUpdatedBody = $this->createMessageWithReplacedAttachmentsInBody($this->message, $attachmentsEmbeddedInMessageBody, $newAttachments);
662
663 if ($this->message->body !== $messageWithUpdatedBody->body)
664 {
665 $this->message->body = $messageWithUpdatedBody->body;
666
667 MailMessageTable::update(
668 $this->message->id,
669 [
670 'BODY_HTML' => $this->message->body,
671 ]
672 );
673 }
674
675 $this->deleteAttachedFromDB($this->message, $oldAttachments);
676
677 $messageWithNewAttachmentCount = $this->createMessageWithAttachmentCount($this->message, count($newAttachments));
678
679 if ($messageWithNewAttachmentCount->attachmentsCount !== $this->message->attachmentsCount)
680 {
681 $this->message->attachmentsCount = $messageWithNewAttachmentCount->attachmentsCount;
682
683 MailMessageTable::update(
684 $this->message->id,
685 [
686 'ATTACHMENTS' => $this->message->attachmentsCount,
687 ]
688 );
689 }
690
691 return true;
692 }
693
701 private function createMessageWithAttachmentCount(MessageStructure $messageStructure, ?int $attachmentCount = null): MessageStructure
702 {
703 $extendedStructure = clone $messageStructure;
704
705 if (is_null($attachmentCount))
706 {
707 $modelRow = MailMessageTable::getRow([
708 'select' => [
709 'ATTACHMENTS'
710 ],
711 'filter' => [
712 'ID' => $messageStructure->id,
713 ],
714 ]);
715
716 if (isset($modelRow['ATTACHMENTS']))
717 {
718 $extendedStructure->attachmentsCount = (int) $modelRow['ATTACHMENTS'];
719 }
720 else
721 {
722 $extendedStructure->attachmentsCount = 0;
723 }
724 }
725 else
726 {
727 $extendedStructure->attachmentsCount = $attachmentCount;
728 }
729
730 return $extendedStructure;
731 }
732
733 private function downloadMessageParts(string $dirPath, string $uid, Imap\BodyStructure $bodyStructure, int $type = self::MESSAGE_PARTS_ALL): array
734 {
735 $messagePartsMetadata = [];
736
737 $fetchCommands = array_filter(
738 $bodyStructure->traverse(
739 function (Imap\BodyStructure $item) use ($type, &$messagePartsMetadata)
740 {
741 if ($item->isMultipart())
742 {
743 return null;
744 }
745
746 $isTextItem = $item->isBodyText();
747
748 if ($type === ($isTextItem ? self::MESSAGE_PARTS_TEXT : self::MESSAGE_PARTS_ATTACHMENT))
749 {
750 //Due to yandex bug
751 if ($item->getType() === 'message' && $item->getSubtype() === 'rfc822')
752 {
753 $messagePartsMetadata[] = $item;
754
755 return sprintf('BODY.PEEK[%1$s.HEADER] BODY.PEEK[%1$s.TEXT]', $item->getNumber());
756 }
757
758 return sprintf('BODY.PEEK[%1$s.MIME] BODY.PEEK[%1$s]', $item->getNumber());
759 }
760 return null;
761 },
762 true
763 )
764 );
765
766 if (empty($fetchCommands))
767 {
768 return [];
769 }
770
771 $error = [];
772
773 $fetchedParts = $this->client->fetch(
774 true,
775 $dirPath,
776 $uid,
777 sprintf('(%s)', join(' ', $fetchCommands)),
778 $error
779 );
780
781 if ($fetchedParts === false)
782 {
783 return [];
784 }
785
786 return $this->combineMessageParts($fetchedParts, $messagePartsMetadata);
787 }
788
799 private function combineMessageParts(array $fetchedParts, array $messagePartsMetadata): array
800 {
802 foreach ($messagePartsMetadata as $item)
803 {
804 $headerKey = sprintf('BODY[%s.HEADER]', $item->getNumber());
805 $bodyKey = sprintf('BODY[%s.TEXT]', $item->getNumber());
806
807 if (array_key_exists($headerKey, $fetchedParts) || array_key_exists($bodyKey, $fetchedParts))
808 {
809 $partMime = 'Content-Type: message/rfc822';
810
811 if (!empty($item->getParams()['name']))
812 {
813 $partMime .= sprintf('; name="%s"', $item->getParams()['name']);
814 }
815
816 if (!empty($item->getDisposition()[0]))
817 {
818 $partMime .= sprintf("\r\nContent-Disposition: %s", $item->getDisposition()[0]);
819
820 if (!empty($item->getDisposition()[1]) && is_array($item->getDisposition()[1]))
821 {
822 foreach ($item->getDisposition()[1] as $name => $value)
823 {
824 $partMime .= sprintf('; %s="%s"', $name, $value);
825 }
826 }
827 }
828
829 $fetchedParts[sprintf('BODY[%1$s.MIME]', $item->getNumber())] = $partMime;
830
831 $fetchedParts[sprintf('BODY[%1$s]', $item->getNumber())] = sprintf(
832 "%s\r\n\r\n%s",
833 rtrim($fetchedParts[$headerKey], "\r\n"),
834 ltrim($fetchedParts[$bodyKey], "\r\n")
835 );
836
837 unset($fetchedParts[$headerKey], $fetchedParts[$bodyKey]);
838 }
839 }
840
841 return $fetchedParts;
842 }
843
844}
$type
Определения options.php:106
if(! $messageFields||!isset($messageFields['message_id'])||!isset($messageFields['status'])||!CModule::IncludeModule("messageservice")) $messageId
Определения callback_ismscenter.php:26
static generateFileName(int $mailboxId, int $messageId, int $attachmentIndex, ?string $attachmentType)
Определения attachmenthelper.php:146
static generateMessageAttachmentPath()
Определения attachmenthelper.php:93
extractFileIdsFromMessageBody(MessageStructure $messageStructure)
Определения attachmenthelper.php:430
__construct(int $mailboxId, int $messageId=null, int $messageUid=null)
Определения attachmenthelper.php:98
__construct(public ?string $name, public ?int $size, public ?string $type, public ?string $content=null, public ?int $diskId=null, public ?int $imageWidth=null, public ?int $imageHeight=null, public ?string $contentId=null, public ?int $attachmentId=null,)
Определения attachmenthelper.php:17
__construct(public int $mailboxId, public string $dirPath, public string $uid, public int $id, public ?int $attachmentsCount=null, public ?string $body=null,)
Определения attachmenthelper.php:33
static getMessage(int $mailboxId, $select, int $id=null, int $uid=null,)
Определения mailmessageuid.php:259
static decodeMessageBody($header, $body, $charset)
Определения mail.php:1531
static parseHeader($header, $charset)
Определения mail.php:1524
$content
Определения commerceml.php:144
$data['IS_AVAILABLE']
Определения .description.php:13
if(errorBox) return true
Определения file_new.php:1035
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$result
Определения get_property_values.php:14
$uid
Определения hot_keys_act.php:8
is_set($a, $k=false)
Определения tools.php:2133
$name
Определения menu_edit.php:35
trait Error
Определения error.php:11
$dir
Определения quickway.php:303
$fileName
Определения quickway.php:305
</p ></td >< td valign=top style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 2.0pt 0cm 2.0pt;height:9.0pt'>< p class=Normal align=center style='margin:0cm;margin-bottom:.0001pt;text-align:center;line-height:normal'>< a name=ТекстовоеПоле54 ></a ><?=($taxRate > count( $arTaxList) > 0) ? $taxRate."%"
Определения waybill.php:936
if(!Loader::includeModule('sale')) $pattern
Определения index.php:20
$matches
Определения index.php:22
$contentId
Определения sonet_set_content_view.php:27
$error
Определения subscription_card_product.php:20