diff --git a/runtime/history/SUPPORT-260918-GRAM-SUPPORT-SCREENSHOT-CONTENTTYPE-RCA-READONLY-516R6R2.json b/runtime/history/SUPPORT-260918-GRAM-SUPPORT-SCREENSHOT-CONTENTTYPE-RCA-READONLY-516R6R2.json new file mode 100644 index 00000000..91a15547 --- /dev/null +++ b/runtime/history/SUPPORT-260918-GRAM-SUPPORT-SCREENSHOT-CONTENTTYPE-RCA-READONLY-516R6R2.json @@ -0,0 +1,38 @@ +{ + "schema_version": 1, + "channel": "homelab-runtime", + "command_id": "SUPPORT-260918-GRAM-SUPPORT-SCREENSHOT-CONTENTTYPE-RCA-READONLY-516R6R2", + "status": "OK", + "rc": 0, + "host": "pve01", + "mode": "read-only", + "component": "gram-support-screenshot-contenttype-rca-readonly", + "started_at_utc": "2026-09-18T06:35:41Z", + "finished_at_utc": "2026-09-18T06:35:43Z", + "reference_register_checked": true, + "reference_sha256": "5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66", + "error_register_checked": true, + "error_register_sha256": "3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0", + "command_sha256": "ebcb50c8b6611004b35a22ff7b9d84652a06563de483931394a777d1fe34d9ba", + "duplicate_failed_command_blocked": false, + "block_reason": null, + "execution_started": true, + "change_declared": false, + "result_contract_valid": true, + "result_contract_status": null, + "result_contract_error": null, + "command_rc": 0, + "changes_made": false, + "rollback_started": false, + "rollback_restored": null, + "mutation_outcome": "NO_MUTATION", + "sanitized": true, + "secrets_included": false, + "private_addresses_included": false, + "raw_evidence_retained_locally": true, + "raw_evidence_sha256": "5d03f3bf31b0f910209d8c1ee71b10d44c31a6abe2f2903eb50a69c18e873f4b", + "sanitized_output_sha256": "5d03f3bf31b0f910209d8c1ee71b10d44c31a6abe2f2903eb50a69c18e873f4b", + "output_truncated_in_json": false, + "full_sanitized_output_url": "https://git.gram1.ru/.well-known/homelab-runtime/latest.txt", + "output": "GRAM516R6R2_SAFE_REPORT={\"err_truncated\":false,\"guest\":{\"error\":null,\"file_count\":51,\"files\":[{\"bytes\":2741,\"path\":\"Service/GuestScreenshotService.php\",\"present\":true,\"sha256\":\"9c0cbf49c4fca5a632a651a288063bc63f9a7ef85f04b32c96b96dd8c9e13e02\",\"text\":\"setAllowedExtensions(['gif', 'jpeg', 'jpg', 'jpe', 'png', 'webp']);\\n $upload->requireImage();\\n\\n $errors = [];\\n if (!$upload->isValid($errors))\\n {\\n throw new \\\\InvalidArgumentException((string)(reset($errors) ?: 'Invalid screenshot.'));\\n }\\n\\n /** @var \\\\XF\\\\Repository\\\\AttachmentRepository $attachmentRepo */\\n $attachmentRepo = \\\\XF::repository('XF:Attachment');\\n $handler = new TicketHandler(self::CONTENT_TYPE);\\n\\n $manipulator = new \\\\XF\\\\Attachment\\\\Manipulator(\\n $handler,\\n $attachmentRepo,\\n [],\\n $tempHash\\n );\\n\\n $error = null;\\n $attachment = $manipulator->insertAttachmentFromUpload($upload, $error);\\n if (!$attachment)\\n {\\n throw new \\\\RuntimeException((string)($error ?: 'Screenshot upload failed.'));\\n }\\n\\n return (int)$attachment->attachment_id;\\n }\\n\\n public function associatePreparedUpload(\\n string $tempHash,\\n Ticket $ticket,\\n int $attachmentId,\\n bool $isInternal = false,\\n int $messageId = 0\\n ): int\\n {\\n if ($tempHash === '' || $attachmentId < 1 || !$ticket->ticket_id)\\n {\\n throw new \\\\InvalidArgumentException('Invalid screenshot association state.');\\n }\\n\\n /** @var \\\\XF\\\\Service\\\\Attachment\\\\PreparerService $preparer */\\n $preparer = \\\\XF::service(\\\\XF\\\\Service\\\\Attachment\\\\PreparerService::class);\\n\\n $associated = (int)$preparer->associateAttachmentsWithContent(\\n $tempHash,\\n self::CONTENT_TYPE,\\n (int)$ticket->ticket_id\\n );\\n\\n if ($associated < 1)\\n {\\n throw new \\\\RuntimeException('No screenshot attachment was associated.');\\n }\\n\\n $meta = \\\\XF::em()->find('Gram\\\\Support:AttachmentMeta', $attachmentId);\\n if (!$meta)\\n {\\n $meta = \\\\XF::em()->create('Gram\\\\Support:AttachmentMeta');\\n $meta->attachment_id = $attachmentId;\\n }\\n\\n $meta->ticket_id = (int)$ticket->ticket_id;\\n $meta->message_id = max(0, $messageId);\\n $meta->is_internal = $isInternal ? 1 : 0;\\n $meta->created_date = \\\\XF::$time;\\n $meta->save();\\n\\n return $associated;\\n }\\n}\\n\"},{\"bytes\":955,\"path\":\"Service/GuestTicketCreateAttachmentFlow.php\",\"present\":true,\"sha256\":\"8f4bf8ed6fa0244e6195d7f91bdbdfd0bc7c9ec7d88b1fe5111377a68b8c0266\",\"text\":\"screenshots = new GuestScreenshotService();\\n }\\n\\n public function prepare(?Upload $upload, string $tempHash): int\\n {\\n if (!$upload)\\n {\\n return 0;\\n }\\n\\n return $this->screenshots->prepareInitialUpload($upload, $tempHash);\\n }\\n\\n public function complete(\\n ?Upload $upload,\\n string $tempHash,\\n Ticket $ticket,\\n int $attachmentId\\n ): void\\n {\\n if (!$upload || $attachmentId < 1)\\n {\\n return;\\n }\\n\\n $this->screenshots->associatePreparedUpload(\\n $tempHash,\\n $ticket,\\n $attachmentId,\\n false,\\n (int)$ticket->last_message_id\\n );\\n }\\n}\\n\"},{\"bytes\":2689,\"path\":\"Entity/Ticket.php\",\"present\":true,\"sha256\":\"f322695057ada74af17de2498dd171c64c6be5bb7eb082388ad94301b13f9eae\",\"text\":\"table = 'xf_gram_support_ticket';\\n $structure->shortName = 'Gram\\\\Support:Ticket';\\n $structure->contentType = 'gram_support_ticket';\\n $structure->primaryKey = 'ticket_id';\\n $structure->columns = [\\n 'ticket_id' => ['type' => self::UINT, 'autoIncrement' => true, 'nullable' => true],\\n 'public_ref' => ['type' => self::STR, 'nullable' => false, 'maxLength' => 64],\\n 'site_id' => ['type' => self::STR, 'nullable' => false, 'maxLength' => 32],\\n 'user_id' => ['type' => self::UINT, 'default' => 0, 'nullable' => false],\\n 'guest_email' => ['type' => self::STR, 'default' => '', 'nullable' => false, 'maxLength' => 255],\\n 'guest_access_token_hash' => ['type' => self::STR, 'default' => '', 'nullable' => false, 'maxLength' => 64],\\n 'guest_access_expires' => ['type' => self::UINT, 'default' => 0, 'nullable' => false],\\n 'node_id' => ['type' => self::UINT, 'default' => 0, 'nullable' => false],\\n 'thread_id' => ['type' => self::UINT, 'default' => 0, 'nullable' => false],\\n 'post_id' => ['type' => self::UINT, 'default' => 0, 'nullable' => false],\\n 'category' => ['type' => self::STR, 'nullable' => false, 'maxLength' => 64],\\n 'subject' => ['type' => self::STR, 'nullable' => false, 'maxLength' => 255],\\n 'status' => ['type' => self::STR, 'nullable' => false, 'maxLength' => 32],\\n 'assigned_user_id' => ['type' => self::UINT, 'default' => 0, 'nullable' => false],\\n 'created_date' => ['type' => self::UINT, 'default' => 0, 'nullable' => false],\\n 'updated_date' => ['type' => self::UINT, 'default' => 0, 'nullable' => false],\\n 'resolved_date' => ['type' => self::UINT, 'default' => 0, 'nullable' => false],\\n 'context_json' => ['type' => self::STR, 'nullable' => false, 'default' => ''],\\n 'last_message_id' => ['type' => self::UINT, 'default' => 0, 'nullable' => false]\\n ];\\n\\n $structure->relations = [\\n 'Attachments' => [\\n 'entity' => 'XF:Attachment',\\n 'type' => self::TO_MANY,\\n 'conditions' => [\\n ['content_type', '=', 'gram_support_ticket'],\\n ['content_id', '=', '$ticket_id']\\n ],\\n 'with' => 'Data',\\n 'order' => 'attach_date'\\n ]\\n ];\\n\\n return $structure;\\n }\\n}\\n\"},{\"bytes\":6301,\"path\":\"Setup.php\",\"present\":true,\"sha256\":\"4977f90ec0444e2e3a1e4ee9b79a4e88098c5a3ae37b30d63e77cff2e1fcb971\",\"text\":\"schemaManager();\\n $sm->createTable('xf_gram_support_ticket', function($table) {\\n $table->addColumn('ticket_id', 'int')->unsigned()->autoIncrement();\\n $table->addColumn('public_ref', 'varchar', 64);\\n $table->addColumn('site_id', 'varchar', 32);\\n $table->addColumn('user_id', 'int')->unsigned()->setDefault(0);\\n $table->addColumn('guest_email', 'varchar', 255)->setDefault('');\\n $table->addColumn('guest_access_token_hash', 'char', 64)->setDefault('');\\n $table->addColumn('guest_access_expires', 'int')->unsigned()->setDefault(0);\\n $table->addColumn('node_id', 'int')->unsigned()->setDefault(0);\\n $table->addColumn('thread_id', 'int')->unsigned()->setDefault(0);\\n $table->addColumn('post_id', 'int')->unsigned()->setDefault(0);\\n $table->addColumn('category', 'varchar', 64)->setDefault('');\\n $table->addColumn('subject', 'varchar', 255)->setDefault('');\\n $table->addColumn('status', 'varchar', 32)->setDefault('NEW');\\n $table->addColumn('assigned_user_id', 'int')->unsigned()->setDefault(0);\\n $table->addColumn('created_date', 'int')->unsigned()->setDefault(0);\\n $table->addColumn('updated_date', 'int')->unsigned()->setDefault(0);\\n $table->addColumn('resolved_date', 'int')->unsigned()->setDefault(0);\\n $table->addColumn('context_json', 'mediumtext');\\n $table->addColumn('last_message_id', 'int')->unsigned()->setDefault(0);\\n $table->addPrimaryKey('ticket_id');\\n $table->addUniqueKey('public_ref');\\n $table->addKey('guest_access_token_hash', 'guest_token_hash');\\n $table->addKey(['site_id','user_id','updated_date'], 'site_user_updated');\\n $table->addKey(['site_id','status','updated_date'], 'site_status_updated');\\n });\\n $sm->createTable('xf_gram_support_message', function($table) {\\n $table->addColumn('message_id', 'int')->unsigned()->autoIncrement();\\n $table->addColumn('ticket_id', 'int')->unsigned();\\n $table->addColumn('user_id', 'int')->unsigned()->setDefault(0);\\n $table->addColumn('is_staff', 'tinyint')->unsigned()->setDefault(0);\\n $table->addColumn('is_internal', 'tinyint')->unsigned()->setDefault(0);\\n $table->addColumn('message', 'mediumtext');\\n $table->addColumn('message_date', 'int')->unsigned()->setDefault(0);\\n $table->addPrimaryKey('message_id');\\n $table->addKey(['ticket_id','message_date'], 'ticket_date');\\n $table->addKey(['ticket_id','is_internal','message_date'], 'ticket_public_date');\\n });\\n $sm->createTable('xf_gram_support_event', function($table) {\\n $table->addColumn('event_id', 'int')->unsigned()->autoIncrement();\\n $table->addColumn('ticket_id', 'int')->unsigned();\\n $table->addColumn('site_id', 'varchar', 32);\\n $table->addColumn('actor_user_id', 'int')->unsigned()->setDefault(0);\\n $table->addColumn('event_type', 'varchar', 64);\\n $table->addColumn('event_date', 'int')->unsigned()->setDefault(0);\\n $table->addColumn('safe_payload_json', 'mediumtext');\\n $table->addPrimaryKey('event_id');\\n $table->addKey(['ticket_id','event_date'], 'ticket_date');\\n });\\n\\n $sm->createTable('xf_gram_support_attachment_meta', function($table) {\\n $table->addColumn('attachment_id', 'int')->unsigned();\\n $table->addColumn('ticket_id', 'int')->unsigned();\\n $table->addColumn('message_id', 'int')->unsigned()->setDefault(0);\\n $table->addColumn('is_internal', 'tinyint')->unsigned()->setDefault(0);\\n $table->addColumn('created_date', 'int')->unsigned()->setDefault(0);\\n $table->addPrimaryKey('attachment_id');\\n $table->addKey(['ticket_id','is_internal'], 'ticket_internal');\\n $table->addKey('message_id');\\n });\\n $sm->createTable('xf_gram_support_delivery', function($table) {\\n $table->addColumn('delivery_key', 'char', 64);\\n $table->addColumn('event_id', 'int')->unsigned();\\n $table->addColumn('consumer', 'varchar', 32);\\n $table->addColumn('recipient_key', 'varchar', 96);\\n $table->addColumn('state', 'varchar', 16)->setDefault('pending');\\n $table->addColumn('lease_expires', 'int')->unsigned()->setDefault(0);\\n $table->addColumn('attempt_count', 'int')->unsigned()->setDefault(0);\\n $table->addColumn('last_failure_class', 'varchar', 191)->setDefault('');\\n $table->addColumn('created_date', 'int')->unsigned()->setDefault(0);\\n $table->addColumn('updated_date', 'int')->unsigned()->setDefault(0);\\n $table->addColumn('sent_date', 'int')->unsigned()->setDefault(0);\\n $table->addPrimaryKey('delivery_key');\\n $table->addKey(['event_id','consumer'], 'event_consumer');\\n $table->addKey(['state','lease_expires'], 'state_lease');\\n });\\n $sm->createTable('xf_gram_support_rate_limit', function($table) {\\n $table->addColumn('rate_key', 'char', 64);\\n $table->addColumn('window_start', 'int')->unsigned();\\n $table->addColumn('hit_count', 'int')->unsigned()->setDefault(0);\\n $table->addColumn('updated_date', 'int')->unsigned()->setDefault(0);\\n $table->addPrimaryKey('rate_key');\\n $table->addKey('updated_date');\\n });\\n }\\n\\n public function uninstallStep1(): void\\n {\\n $sm = $this->schemaManager();\\n foreach (['xf_gram_support_attachment_meta','xf_gram_support_delivery','xf_gram_support_rate_limit','xf_gram_support_event','xf_gram_support_message','xf_gram_support_ticket'] as $name) {\\n $sm->dropTable($name);\\n }\\n }\\n}\\n\"},{\"bytes\":212,\"path\":\"_data/content_type_fields.xml\",\"present\":true,\"sha256\":\"6f9760bc6cc3c78aaec3a1ad68bcbc180d6cd4d2ef30830a4dc3b7b500a0cc97\",\"text\":\"\\n\\n Gram\\\\Support\\\\Attachment\\\\TicketHandler\\n\\n\"},{\"bytes\":26547,\"matches\":[{\"sep\":true},{\"line\":616,\"text\":\"\\tconst request = event.request;\"},{\"line\":617,\"text\":\"\\tif (request.method !== 'GET') {\"},{\"line\":618,\"text\":\"\\t\\treturn;\"},{\"line\":619,\"text\":\"\\t}\"},{\"line\":620,\"text\":\"\"},{\"line\":621,\"text\":\"\\tconst url = new URL(request.url);\"},{\"line\":622,\"text\":\"\\tif (url.origin !== self.location.origin) {\"},{\"line\":623,\"text\":\"\\t\\treturn;\"},{\"line\":624,\"text\":\"\\t}\"},{\"line\":625,\"text\":\"\"},{\"line\":626,\"text\":\"\\t// SECURITY: all support/ticket/account/admin-like content is network-only.\"},{\"line\":627,\"text\":\"\\t// Never cache HTML/API responses that can contain ticket data, identities,\"},{\"line\":628,\"text\":\"\\t// access state, internal notes, attachments or staff-only information.\"},{\"line\":629,\"text\":\"\\tconst sensitive =\"},{\"line\":630,\"text\":\"\\t\\turl.pathname.startsWith('/support/') ||\"},{\"line\":631,\"text\":\"\\t\\turl.pathname.startsWith('/account/') ||\"},{\"line\":632,\"text\":\"\\t\\turl.pathname.startsWith('/admin.php') ||\"},{\"line\":633,\"text\":\"\\t\\trequest.headers.get('accept')?.includes('text/html');\"},{\"line\":634,\"text\":\"\"},{\"line\":635,\"text\":\"\\tif (sensitive) {\"},{\"line\":636,\"text\":\"\\t\\tevent.respondWith(\"},{\"line\":637,\"text\":\"\\t\\t\\tfetch(request, {cache: 'no-store'}).catch(() => {\"},{\"line\":638,\"text\":\"\\t\\t\\t\\tif (request.mode === 'navigate') {\"},{\"line\":639,\"text\":\"\\t\\t\\t\\t\\treturn caches.match(OFFLINE_URL);\"},{\"line\":640,\"text\":\"\\t\\t\\t\\t}\"},{\"sep\":true},{\"line\":676,\"text\":\"\\t\\t\\t\\t\\t<div class=\\\"gramSupport-messageMeta\\\">\"},{\"line\":677,\"text\":\"\\t\\t\\t\\t\\t\\t{{ date_time($message.message_date) }}\"},{\"line\":678,\"text\":\"\\t\\t\\t\\t\\t\\t<xf:if is=\\\"$message.is_internal\\\"> \\u00b7 {{ phrase('gram_support_internal_note') }}</xf:if>\"},{\"line\":679,\"text\":\"\\t\\t\\t\\t\\t</div>\"},{\"line\":680,\"text\":\"\\t\\t\\t\\t\\t<div class=\\\"gramSupport-messageBody\\\">{$message.message}</div>\"},{\"line\":681,\"text\":\"\\t\\t\\t\\t</div>\"},{\"line\":682,\"text\":\"\\t\\t\\t</xf:foreach>\"},{\"line\":683,\"text\":\"\\t\\t</div>\"},{\"line\":684,\"text\":\"\\t</div>\"},{\"line\":685,\"text\":\"</div>\"},{\"line\":686,\"text\":\"\"},{\"line\":687,\"text\":\"\"},{\"line\":688,\"text\":\"<xf:if is=\\\"$ticket.Attachments is not empty\\\">\"},{\"line\":689,\"text\":\"\\t<div class=\\\"block\\\">\"},{\"line\":690,\"text\":\"\\t\\t<div class=\\\"block-container\\\">\"},{\"line\":691,\"text\":\"\\t\\t\\t<h3 class=\\\"block-minorHeader\\\">{{ phrase('gram_support_attachments') }}</h3>\"},{\"line\":692,\"text\":\"\\t\\t\\t<div class=\\\"block-body\\\">\"},{\"line\":693,\"text\":\"\\t\\t\\t\\t<xf:foreach loop=\\\"$ticket.Attachments\\\" value=\\\"$attachment\\\">\"},{\"line\":694,\"text\":\"\\t\\t\\t\\t\\t<div class=\\\"block-row\\\">\"},{\"line\":695,\"text\":\"\\t\\t\\t\\t\\t\\t<a href=\\\"{{ link('attachments', $attachment) }}\\\">{$attachment.filename}</a>\"},{\"line\":696,\"text\":\"\\t\\t\\t\\t\\t</div>\"},{\"line\":697,\"text\":\"\\t\\t\\t\\t</xf:foreach>\"},{\"line\":698,\"text\":\"\\t\\t\\t</div>\"},{\"line\":699,\"text\":\"\\t\\t</div>\"},{\"line\":700,\"text\":\"\\t</div>\"},{\"line\":701,\"text\":\"</xf:if>\"},{\"line\":702,\"text\":\"\"},{\"line\":703,\"text\":\"<xf:form action=\\\"{{ link('support/staff/reply', null, {'ref': $ticket.public_ref}) }}\\\" method=\\\"post\\\" class=\\\"block\\\">\"},{\"line\":704,\"text\":\"\\t<div class=\\\"block-container\\\">\"},{\"line\":705,\"text\":\"\\t\\t<div class=\\\"block-body\\\">\"},{\"line\":706,\"text\":\"\\t\\t\\t<xf:textarearow name=\\\"message\\\" required=\\\"required\\\" rows=\\\"6\\\" label=\\\"{{ phrase('gram_support_reply') }}\\\" />\"},{\"line\":707,\"text\":\"\\t\\t\\t<xf:if is=\\\"$xf.visitor.hasPermission('gramSupport', 'internalNotes')\\\">\"},{\"sep\":true},{\"line\":720,\"text\":\"\\t\\t\\t<xf:selectrow name=\\\"status\\\" value=\\\"{$ticket.status}\\\" label=\\\"{{ phrase('gram_support_status') }}\\\">\"},{\"line\":721,\"text\":\"\\t\\t\\t\\t<xf:foreach loop=\\\"$statusOptions\\\" value=\\\"$status\\\">\"},{\"line\":722,\"text\":\"\\t\\t\\t\\t\\t<xf:option value=\\\"{$status}\\\">{{ $status == 'NEW' ? '\\u041d\\u043e\\u0432\\u044b\\u0439' : ($status == 'IN_PROGRESS' ? '\\u0412 \\u0440\\u0430\\u0431\\u043e\\u0442\\u0435' : ($status == 'WAITING_USER' ? '\\u041e\\u0436\\u0438\\u0434\\u0430\\u0435\\u0442 \\u043e\\u0442\\u0432\\u0435\\u0442\\u0430 \\u043f\\u043e\\u043b\\u044c\\u0437\\u043e\\u0432\\u0430\\u0442\\u0435\\u043b\\u044f' : ($status == 'RESOLVED' ? '\\u0420\\u0435\\u0448\\u0451\\u043d' : ($status == 'CLOSED' ? '\\u0417\\u0430\\u043a\\u0440\\u044b\\u0442' : $status)))) }}</xf:option>\"},{\"line\":723,\"text\":\"\\t\\t\\t\\t</xf:foreach>\"},{\"line\":724,\"text\":\"\\t\\t\\t</xf:selectrow>\"},{\"line\":725,\"text\":\"\\t\\t\\t<xf:textboxrow name=\\\"assigned_user_id\\\" type=\\\"number\\\" value=\\\"{$ticket.assigned_user_id}\\\"\"},{\"line\":726,\"text\":\"\\t\\t\\t\\tlabel=\\\"{{ phrase('gram_support_assigned_user_id') }}\\\" />\"},{\"line\":727,\"text\":\"\\t\\t</div>\"},{\"line\":728,\"text\":\"\\t\\t<xf:submitrow submit=\\\"{{ phrase('save') }}\\\" />\"},{\"line\":729,\"text\":\"\\t</div>\"},{\"line\":730,\"text\":\"</xf:form>\"},{\"line\":731,\"text\":\"\"},{\"line\":732,\"text\":\" \"},{\"line\":786,\"text\":\" \"},{\"line\":794,\"text\":\" \"},{\"line\":803,\"text\":\"\"}],\"path\":\"_data/templates.xml\",\"present\":true,\"sha256\":\"04ed000e02dd040f0587cf276f8c2ad332b568c951b58bd5767df78406e10239\"},{\"bytes\":6986,\"path\":\"hashes.json\",\"present\":true,\"sha256\":\"bb009f37cf73670d20a66d18931a0344a648b6a44305094e0278960bfbfe2b65\",\"text\":\"{\\n \\\"js/gram/support/access.js\\\": \\\"4140aef30c7c39d102af5efd64d38dae54b810945d96faa8884fd00eaab31358\\\",\\n \\\"js/gram/support/access.min.js\\\": \\\"4140aef30c7c39d102af5efd64d38dae54b810945d96faa8884fd00eaab31358\\\",\\n \\\"js/gram/support/pwa/icon-192.png\\\": \\\"1c52e67c4a4963f3a134f9cea0a695702eae06ed2e62ccacd67f2efa2bc692e2\\\",\\n \\\"js/gram/support/pwa/icon-512.png\\\": \\\"66f60c10b8c7d67e432c9fb701c1cde6130e4bc18788a7d9c470c0c6fdd9cfd4\\\",\\n \\\"js/gram/support/pwa/manifest.webmanifest\\\": \\\"49224d92b3a98f447b63e1f4a1a14c106e31a9392b202826979f7d9391a03732\\\",\\n \\\"js/gram/support/pwa/offline.html\\\": \\\"7cbf2c5efa2cf3e5bb479d01e1b1b68f45fa0877de6a5f867c34ea6a312e6901\\\",\\n \\\"js/gram/support/staff-pwa.js\\\": \\\"026b270bee0103d42c2881017b885bd2c6ad67b9482b323fbd5a2297dbd4247c\\\",\\n \\\"js/gram/support/staff-pwa.min.js\\\": \\\"026b270bee0103d42c2881017b885bd2c6ad67b9482b323fbd5a2297dbd4247c\\\",\\n \\\"src/addons/Gram/Support/Attachment/TicketHandler.php\\\": \\\"0def74cda843a56cdea03a8f9c40156a86424de6a09ce64ced655e5f0458361a\\\",\\n \\\"src/addons/Gram/Support/Entity/AttachmentMeta.php\\\": \\\"e19fbc558741df7fbad0b1cbd68b6f1c149db4544deb97bfd9432d6c44c27b5d\\\",\\n \\\"src/addons/Gram/Support/Entity/Delivery.php\\\": \\\"034fa397e67003884d197908a0b4ba968aea4832684c9e12aeff495c4378e551\\\",\\n \\\"src/addons/Gram/Support/Entity/Message.php\\\": \\\"f8a38d779917d577a3c17ecdb4606505bdd4f1588a091e8f89f775c7c60c8342\\\",\\n \\\"src/addons/Gram/Support/Entity/RateLimit.php\\\": \\\"d964076da9a290c505bf0798b00b6a9677520d4a925b8771f066d48b3c516783\\\",\\n \\\"src/addons/Gram/Support/Entity/SupportEvent.php\\\": \\\"b9c68bda7488e167cf437061e547646db27b60976d8a2d2ae39d8cb914223723\\\",\\n \\\"src/addons/Gram/Support/Entity/Ticket.php\\\": \\\"f322695057ada74af17de2498dd171c64c6be5bb7eb082388ad94301b13f9eae\\\",\\n \\\"src/addons/Gram/Support/Listener/SourcePageContext.php\\\": \\\"25e449317b7b48959aad49e1b73f785c84d0e14bd9d6fa55d7e3cb8ac074b253\\\",\\n \\\"src/addons/Gram/Support/Notification/AlertConsumer.php\\\": \\\"e22d0cdb0a0806c6a231504409bd17cd781caab0f28181aff7246b0295d8cd98\\\",\\n \\\"src/addons/Gram/Support/Notification/DeliveryGate.php\\\": \\\"32447f0066a3153e241424ef6f87459ad9aa067c389a693cc98a21498bbd5d7b\\\",\\n \\\"src/addons/Gram/Support/Notification/Dispatcher.php\\\": \\\"faa370b6b2abda1defa4a1d49aeb448a5f16f8013add4cd1975cc3b65eecda2b\\\",\\n \\\"src/addons/Gram/Support/Notification/EmailConsumer.php\\\": \\\"d1928ebb89483fbc59ac0323cfaabb064e8e6281d4927666c63568ac540e7a34\\\",\\n \\\"src/addons/Gram/Support/Notification/EntityDeliveryGate.php\\\": \\\"188ddc86845c0cef16d1749a2bc6824c199a5d99dd9acbbc610b8e23439ec4f4\\\",\\n \\\"src/addons/Gram/Support/Notification/EventDispatcher.php\\\": \\\"7b5be9cd2421aa365a618687e7af43e2d8320515bd85f90a23877c30c92b0817\\\",\\n \\\"src/addons/Gram/Support/Notification/Policy.php\\\": \\\"5fb1f224ab1064f18bb7e8ab9fa7cc4f77c6587ea9a01c7f48c81186e4c618ed\\\",\\n \\\"src/addons/Gram/Support/Notification/RecipientKey.php\\\": \\\"23d7a6793221011de7af02bcac796c8418748758ef3c4185406deaca90a76529\\\",\\n \\\"src/addons/Gram/Support/Pub/Controller/AccountSupport.php\\\": \\\"236e648a240a3bde2721f3d9355ce0c48f81a0b727407e08cbaa563ae2df1dfd\\\",\\n \\\"src/addons/Gram/Support/Pub/Controller/Pwa.php\\\": \\\"9e3217d9524349a8137b89d418e4693ca17f8e5f61ba5b563fff747d1014efb3\\\",\\n \\\"src/addons/Gram/Support/Pub/Controller/StaffSupport.php\\\": \\\"6852bd0061d6e118851673bfd4099e2b22e6291bf09f429820740844996f93f9\\\",\\n \\\"src/addons/Gram/Support/Pub/Controller/Support.php\\\": \\\"6cb34b1d27e9f0132263637cefa62fe0e998a9a86620b7ac33199f41ee86f9d4\\\",\\n \\\"src/addons/Gram/Support/Pub/View/PwaServiceWorker.php\\\": \\\"4bf365039b6deeb476d2137cdea27b5c463f15c54e370e607251db0643c46ae3\\\",\\n \\\"src/addons/Gram/Support/Repository/Message.php\\\": \\\"bd077eaf7070f3c2b23259f51bd98788db4ca5a6efc6fedf98772159fbcd6e19\\\",\\n \\\"src/addons/Gram/Support/Repository/Ticket.php\\\": \\\"051b470f486fccbddf881779327b03f0c804462c4d47de3a11e0ffb62352aad7\\\",\\n \\\"src/addons/Gram/Support/Security/GuestTicketSession.php\\\": \\\"9637043a10b7f2806c50ee9da04ea076d25a6924d7636b0533a2ea59212975e1\\\",\\n \\\"src/addons/Gram/Support/Security/TicketAccess.php\\\": \\\"f486abd65893052dbaafad550ad0d147ba638661e0e7ed73d7e2b3e046bec4a5\\\",\\n \\\"src/addons/Gram/Support/Service/GuestScreenshotService.php\\\": \\\"9c0cbf49c4fca5a632a651a288063bc63f9a7ef85f04b32c96b96dd8c9e13e02\\\",\\n \\\"src/addons/Gram/Support/Service/GuestTicketCreateAttachmentFlow.php\\\": \\\"8f4bf8ed6fa0244e6195d7f91bdbdfd0bc7c9ec7d88b1fe5111377a68b8c0266\\\",\\n \\\"src/addons/Gram/Support/Service/RateLimiter.php\\\": \\\"266b3b39785ae5272f478d3fed527850bda2526fc70ac5122ff663f1c702a360\\\",\\n \\\"src/addons/Gram/Support/Service/SourceContextResolver.php\\\": \\\"a66215ecabacbbad8daa8f1fef95a541a5d6863df2ab977a714737c0a2a76c95\\\",\\n \\\"src/addons/Gram/Support/Service/Ticket/Creator.php\\\": \\\"7a84cd77761a7943495f9d3ef11269987f85265170ad6cf927a1661b8bf0a99a\\\",\\n \\\"src/addons/Gram/Support/Service/Ticket/Reply.php\\\": \\\"482571a2ccf07a3c8672f34940243264a8271ef8c3cbc4fadbb46112afd36830\\\",\\n \\\"src/addons/Gram/Support/Service/Ticket/StaffUpdate.php\\\": \\\"400596fbe4d2f990a5301973318b65f20f2618a34e6b202d975c62bd252eabdf\\\",\\n \\\"src/addons/Gram/Support/Setup.php\\\": \\\"4977f90ec0444e2e3a1e4ee9b79a4e88098c5a3ae37b30d63e77cff2e1fcb971\\\",\\n \\\"src/addons/Gram/Support/Util/GuestToken.php\\\": \\\"4c82936658fa7ca351f5d3d106f82bf49365f571e0fbb53e15de72bc22a746b8\\\",\\n \\\"src/addons/Gram/Support/Util/PublicRef.php\\\": \\\"4dfc846870192d175941546192deaf6dfb68306401b8a368b166975ec67b11a2\\\",\\n \\\"src/addons/Gram/Support/Util/RateKey.php\\\": \\\"cdf0588dff095dbeb89c1ed6e2b12af583c0f6bca2d66de7390e224045c0eac9\\\",\\n \\\"src/addons/Gram/Support/Util/SafeContext.php\\\": \\\"edd58d3135b05cd85d393d3e6f674601d530fb38d9667dbab0e4ddba7db78519\\\",\\n \\\"src/addons/Gram/Support/Util/SiteConfig.php\\\": \\\"db246e35b477c55d4fb1d464b0de0829a91e09ed42058bf704d667ae7b23e3b8\\\",\\n \\\"src/addons/Gram/Support/Util/StatusPolicy.php\\\": \\\"356f4b24d4b2a562105d3c7cc4f83ce198be11d15770c71ec2bf1d9ca43310f7\\\",\\n \\\"src/addons/Gram/Support/_data/code_event_listeners.xml\\\": \\\"b61eea171404d5a64dd639aa6432af83b9dca4d3cab040eaa0496780e9fa34a2\\\",\\n \\\"src/addons/Gram/Support/_data/content_type_fields.xml\\\": \\\"6f9760bc6cc3c78aaec3a1ad68bcbc180d6cd4d2ef30830a4dc3b7b500a0cc97\\\",\\n \\\"src/addons/Gram/Support/_data/option_groups.xml\\\": \\\"357e532805c40e424fec654349241ecb322e1cb8ee2560f9abb964f10a55cdda\\\",\\n \\\"src/addons/Gram/Support/_data/options.xml\\\": \\\"499d0a3b543eb838d5497f2da1b0cd13e5510e9f7e10aded7b06cb422cab8143\\\",\\n \\\"src/addons/Gram/Support/_data/permission_interface_groups.xml\\\": \\\"f54be0d872f43813e0f57d75a73420da70d37091f408d3cbdf9e943d4f67c1ad\\\",\\n \\\"src/addons/Gram/Support/_data/permissions.xml\\\": \\\"c0cf9d60702b670355f3f0928e0afde20a5c7becf065536c3487289211a4bbee\\\",\\n \\\"src/addons/Gram/Support/_data/phrases.xml\\\": \\\"ea6e84de301145312758285cfcd63ee4c12b8e921877bcde15c17dd4c115c434\\\",\\n \\\"src/addons/Gram/Support/_data/routes.xml\\\": \\\"c80e6b0f7153993915d8bbc8ee6b36e6386b00bb1865d6aff050f9c1fd1f0302\\\",\\n \\\"src/addons/Gram/Support/_data/template_modifications.xml\\\": \\\"04f338a8107a80bd3c17b6f6888faea596a5057140556ce6f4f1673d2034628b\\\",\\n \\\"src/addons/Gram/Support/_data/templates.xml\\\": \\\"04ed000e02dd040f0587cf276f8c2ad332b568c951b58bd5767df78406e10239\\\",\\n \\\"src/addons/Gram/Support/addon.json\\\": \\\"566f1739937088517f5ef0dd2d20bc92460084028180c16502931fa86057aea5\\\"\\n}\\n\"}],\"occurrences\":[{\"bytes\":3232,\"hit_count\":18,\"hits\":[{\"line\":3,\"text\":\"namespace Gram\\\\Support\\\\Attachment;\"},{\"line\":5,\"text\":\"use Gram\\\\Support\\\\Entity\\\\Ticket;\"},{\"line\":7,\"text\":\"use XF\\\\Entity\\\\Attachment;\"},{\"line\":8,\"text\":\"use XF\\\\Mvc\\\\Entity\\\\Entity;\"},{\"line\":10,\"text\":\"class TicketHandler extends \\\\XF\\\\Attachment\\\\AbstractHandler\"},{\"line\":12,\"text\":\" public function canView(Attachment $attachment, Entity $container, &$error = null)\"},{\"line\":19,\"text\":\" $meta = \\\\XF::em()->find('Gram\\\\Support:AttachmentMeta', (int)$attachment->attachment_id);\"},{\"line\":40,\"text\":\" public function canManageAttachments(array $context, &$error = null)\"},{\"line\":56,\"text\":\" return TicketAccess::canManageAttachments($ticket, \\\\XF::visitor());\"},{\"line\":59,\"text\":\" public function onAttachmentDelete(Attachment $attachment, Entity $container = null)\"},{\"line\":61,\"text\":\" $meta = \\\\XF::em()->find('Gram\\\\Support:AttachmentMeta', (int)$attachment->attachment_id);\"},{\"line\":70,\"text\":\" $constraints = \\\\XF::repository('XF:Attachment')->getDefaultAttachmentConstraints();\"},{\"line\":80,\"text\":\" public function getContainerLink(Entity $container, array $extraParams = [])\"},{\"line\":96,\"text\":\" public function getContext(Entity $entity = null, array $extraContext = [])\"},{\"line\":98,\"text\":\" if ($entity instanceof Ticket)\"},{\"line\":100,\"text\":\" $extraContext['ticket_id'] = (int)$entity->ticket_id;\"},{\"line\":104,\"text\":\" if ($entity === null)\"},{\"line\":109,\"text\":\" throw new \\\\InvalidArgumentException('Entity must be a support ticket.');\"}],\"path\":\"Attachment/TicketHandler.php\",\"sha256\":\"0def74cda843a56cdea03a8f9c40156a86424de6a09ce64ced655e5f0458361a\"},{\"bytes\":884,\"hit_count\":8,\"hits\":[{\"line\":3,\"text\":\"namespace Gram\\\\Support\\\\Entity;\"},{\"line\":5,\"text\":\"use XF\\\\Mvc\\\\Entity\\\\Entity;\"},{\"line\":6,\"text\":\"use XF\\\\Mvc\\\\Entity\\\\Structure;\"},{\"line\":8,\"text\":\"class AttachmentMeta extends Entity\"},{\"line\":12,\"text\":\" $structure->table = 'xf_gram_support_attachment_meta';\"},{\"line\":13,\"text\":\" $structure->shortName = 'Gram\\\\Support:AttachmentMeta';\"},{\"line\":14,\"text\":\" $structure->primaryKey = 'attachment_id';\"},{\"line\":16,\"text\":\" 'attachment_id' => ['type' => self::UINT, 'nullable' => false],\"}],\"path\":\"Entity/AttachmentMeta.php\",\"sha256\":\"e19fbc558741df7fbad0b1cbd68b6f1c149db4544deb97bfd9432d6c44c27b5d\"},{\"bytes\":1474,\"hit_count\":4,\"hits\":[{\"line\":3,\"text\":\"namespace Gram\\\\Support\\\\Entity;\"},{\"line\":5,\"text\":\"use XF\\\\Mvc\\\\Entity\\\\Entity;\"},{\"line\":6,\"text\":\"use XF\\\\Mvc\\\\Entity\\\\Structure;\"},{\"line\":8,\"text\":\"class Delivery extends Entity\"}],\"path\":\"Entity/Delivery.php\",\"sha256\":\"034fa397e67003884d197908a0b4ba968aea4832684c9e12aeff495c4378e551\"},{\"bytes\":1049,\"hit_count\":4,\"hits\":[{\"line\":2,\"text\":\"namespace Gram\\\\Support\\\\Entity;\"},{\"line\":4,\"text\":\"use XF\\\\Mvc\\\\Entity\\\\Entity;\"},{\"line\":5,\"text\":\"use XF\\\\Mvc\\\\Entity\\\\Structure;\"},{\"line\":7,\"text\":\"class Message extends Entity\"}],\"path\":\"Entity/Message.php\",\"sha256\":\"f8a38d779917d577a3c17ecdb4606505bdd4f1588a091e8f89f775c7c60c8342\"},{\"bytes\":805,\"hit_count\":4,\"hits\":[{\"line\":2,\"text\":\"namespace Gram\\\\Support\\\\Entity;\"},{\"line\":4,\"text\":\"use XF\\\\Mvc\\\\Entity\\\\Entity;\"},{\"line\":5,\"text\":\"use XF\\\\Mvc\\\\Entity\\\\Structure;\"},{\"line\":7,\"text\":\"class RateLimit extends Entity\"}],\"path\":\"Entity/RateLimit.php\",\"sha256\":\"d964076da9a290c505bf0798b00b6a9677520d4a925b8771f066d48b3c516783\"},{\"bytes\":1069,\"hit_count\":4,\"hits\":[{\"line\":2,\"text\":\"namespace Gram\\\\Support\\\\Entity;\"},{\"line\":4,\"text\":\"use XF\\\\Mvc\\\\Entity\\\\Entity;\"},{\"line\":5,\"text\":\"use XF\\\\Mvc\\\\Entity\\\\Structure;\"},{\"line\":7,\"text\":\"class SupportEvent extends Entity\"}],\"path\":\"Entity/SupportEvent.php\",\"sha256\":\"b9c68bda7488e167cf437061e547646db27b60976d8a2d2ae39d8cb914223723\"},{\"bytes\":2689,\"hit_count\":9,\"hits\":[{\"line\":3,\"text\":\"namespace Gram\\\\Support\\\\Entity;\"},{\"line\":5,\"text\":\"use XF\\\\Mvc\\\\Entity\\\\Entity;\"},{\"line\":6,\"text\":\"use XF\\\\Mvc\\\\Entity\\\\Structure;\"},{\"line\":8,\"text\":\"class Ticket extends Entity\"},{\"line\":12,\"text\":\" $structure->table = 'xf_gram_support_ticket';\"},{\"line\":14,\"text\":\" $structure->contentType = 'gram_support_ticket';\"},{\"line\":39,\"text\":\" 'Attachments' => [\"},{\"line\":40,\"text\":\" 'entity' => 'XF:Attachment',\"},{\"line\":43,\"text\":\" ['content_type', '=', 'gram_support_ticket'],\"}],\"path\":\"Entity/Ticket.php\",\"sha256\":\"f322695057ada74af17de2498dd171c64c6be5bb7eb082388ad94301b13f9eae\"},{\"bytes\":2147,\"hit_count\":3,\"hits\":[{\"line\":5,\"text\":\"use Gram\\\\Support\\\\Entity\\\\SupportEvent;\"},{\"line\":6,\"text\":\"use Gram\\\\Support\\\\Entity\\\\Ticket;\"},{\"line\":7,\"text\":\"use XF\\\\Entity\\\\User;\"}],\"path\":\"Notification/AlertConsumer.php\",\"sha256\":\"e22d0cdb0a0806c6a231504409bd17cd781caab0f28181aff7246b0295d8cd98\"},{\"bytes\":1771,\"hit_count\":3,\"hits\":[{\"line\":5,\"text\":\"use Gram\\\\Support\\\\Entity\\\\SupportEvent;\"},{\"line\":6,\"text\":\"use Gram\\\\Support\\\\Entity\\\\Ticket;\"},{\"line\":7,\"text\":\"use XF\\\\Entity\\\\User;\"}],\"path\":\"Notification/Dispatcher.php\",\"sha256\":\"faa370b6b2abda1defa4a1d49aeb448a5f16f8013add4cd1975cc3b65eecda2b\"},{\"bytes\":4045,\"hit_count\":6,\"hits\":[{\"line\":5,\"text\":\"use Gram\\\\Support\\\\Entity\\\\SupportEvent;\"},{\"line\":6,\"text\":\"use Gram\\\\Support\\\\Entity\\\\Ticket;\"},{\"line\":7,\"text\":\"use XF\\\\Entity\\\\User;\"},{\"line\":38,\"text\":\" ->setTemplate('gram_support_ticket_event', [\"},{\"line\":70,\"text\":\" ->setTemplate('gram_support_ticket_event', [\"},{\"line\":105,\"text\":\" ->setTemplate('gram_support_ticket_event_guest', [\"}],\"path\":\"Notification/EmailConsumer.php\",\"sha256\":\"d1928ebb89483fbc59ac0323cfaabb064e8e6281d4927666c63568ac540e7a34\"},{\"bytes\":3504,\"hit_count\":1,\"hits\":[{\"line\":5,\"text\":\"final class EntityDeliveryGate implements DeliveryGate\"}],\"path\":\"Notification/EntityDeliveryGate.php\",\"sha256\":\"188ddc86845c0cef16d1749a2bc6824c199a5d99dd9acbbc610b8e23439ec4f4\"},{\"bytes\":2801,\"hit_count\":3,\"hits\":[{\"line\":5,\"text\":\"use Gram\\\\Support\\\\Entity\\\\SupportEvent;\"},{\"line\":6,\"text\":\"use Gram\\\\Support\\\\Entity\\\\Ticket;\"},{\"line\":14,\"text\":\" $gate = new EntityDeliveryGate();\"}],\"path\":\"Notification/EventDispatcher.php\",\"sha256\":\"7b5be9cd2421aa365a618687e7af43e2d8320515bd85f90a23877c30c92b0817\"},{\"bytes\":1452,\"hit_count\":1,\"hits\":[{\"line\":5,\"text\":\"use Gram\\\\Support\\\\Entity\\\\SupportEvent;\"}],\"path\":\"Notification/Policy.php\",\"sha256\":\"5fb1f224ab1064f18bb7e8ab9fa7cc4f77c6587ea9a01c7f48c81186e4c618ed\"},{\"bytes\":1531,\"hit_count\":1,\"hits\":[{\"line\":50,\"text\":\" 'gram_support_ticket',\"}],\"path\":\"Pub/Controller/AccountSupport.php\",\"sha256\":\"236e648a240a3bde2721f3d9355ce0c48f81a0b727407e08cbaa563ae2df1dfd\"},{\"bytes\":7077,\"hit_count\":6,\"hits\":[{\"line\":8,\"text\":\"use Gram\\\\Support\\\\Service\\\\GuestTicketCreateAttachmentFlow;\"},{\"line\":71,\"text\":\" $attachmentFlow = new GuestTicketCreateAttachmentFlow();\"},{\"line\":73,\"text\":\" $attachmentId = 0;\"},{\"line\":76,\"text\":\" $attachmentId = $attachmentFlow->prepare($upload, $tempHash);\"},{\"line\":99,\"text\":\" $attachmentFlow->complete($upload, $tempHash, $ticket, $attachmentId);\"},{\"line\":180,\"text\":\" 'gram_support_ticket',\"}],\"path\":\"Pub/Controller/Support.php\",\"sha256\":\"6cb34b1d27e9f0132263637cefa62fe0e998a9a86620b7ac33199f41ee86f9d4\"},{\"bytes\":358,\"hit_count\":1,\"hits\":[{\"line\":9,\"text\":\" $this->response->contentType('application/javascript', 'utf-8');\"}],\"path\":\"Pub/View/PwaServiceWorker.php\",\"sha256\":\"4bf365039b6deeb476d2137cdea27b5c463f15c54e370e607251db0643c46ae3\"},{\"bytes\":563,\"hit_count\":1,\"hits\":[{\"line\":5,\"text\":\"use XF\\\\Mvc\\\\Entity\\\\Repository;\"}],\"path\":\"Repository/Message.php\",\"sha256\":\"bd077eaf7070f3c2b23259f51bd98788db4ca5a6efc6fedf98772159fbcd6e19\"},{\"bytes\":1329,\"hit_count\":1,\"hits\":[{\"line\":6,\"text\":\"use XF\\\\Mvc\\\\Entity\\\\Repository;\"}],\"path\":\"Repository/Ticket.php\",\"sha256\":\"051b470f486fccbddf881779327b03f0c804462c4d47de3a11e0ffb62352aad7\"},{\"bytes\":1318,\"hit_count\":1,\"hits\":[{\"line\":5,\"text\":\"use Gram\\\\Support\\\\Entity\\\\Ticket;\"}],\"path\":\"Security/GuestTicketSession.php\",\"sha256\":\"9637043a10b7f2806c50ee9da04ea076d25a6924d7636b0533a2ea59212975e1\"},{\"bytes\":1305,\"hit_count\":3,\"hits\":[{\"line\":5,\"text\":\"use Gram\\\\Support\\\\Entity\\\\Ticket;\"},{\"line\":6,\"text\":\"use XF\\\\Entity\\\\User;\"},{\"line\":33,\"text\":\" public static function canManageAttachments(Ticket $ticket, User $visitor): bool\"}],\"path\":\"Security/TicketAccess.php\",\"sha256\":\"f486abd65893052dbaafad550ad0d147ba638661e0e7ed73d7e2b3e046bec4a5\"},{\"bytes\":2741,\"hit_count\":23,\"hits\":[{\"line\":5,\"text\":\"use Gram\\\\Support\\\\Attachment\\\\TicketHandler;\"},{\"line\":6,\"text\":\"use Gram\\\\Support\\\\Entity\\\\Ticket;\"},{\"line\":9,\"text\":\"final class GuestScreenshotService\"},{\"line\":11,\"text\":\" private const CONTENT_TYPE = 'gram_support_ticket';\"},{\"line\":17,\"text\":\" throw new \\\\InvalidArgumentException('Attachment temp hash must not be empty.');\"},{\"line\":29,\"text\":\" /** @var \\\\XF\\\\Repository\\\\AttachmentRepository $attachmentRepo */\"},{\"line\":30,\"text\":\" $attachmentRepo = \\\\XF::repository('XF:Attachment');\"},{\"line\":31,\"text\":\" $handler = new TicketHandler(self::CONTENT_TYPE);\"},{\"line\":33,\"text\":\" $manipulator = new \\\\XF\\\\Attachment\\\\Manipulator(\"},{\"line\":35,\"text\":\" $attachmentRepo,\"},{\"line\":41,\"text\":\" $attachment = $manipulator->insertAttachmentFromUpload($upload, $error);\"},{\"line\":42,\"text\":\" if (!$attachment)\"},{\"line\":47,\"text\":\" return (int)$attachment->attachment_id;\"},{\"line\":53,\"text\":\" int $attachmentId,\"},{\"line\":58,\"text\":\" if ($tempHash === '' || $attachmentId < 1 || !$ticket->ticket_id)\"},{\"line\":63,\"text\":\" /** @var \\\\XF\\\\Service\\\\Attachment\\\\PreparerService $preparer */\"},{\"line\":64,\"text\":\" $preparer = \\\\XF::service(\\\\XF\\\\Service\\\\Attachment\\\\PreparerService::class);\"},{\"line\":66,\"text\":\" $associated = (int)$preparer->associateAttachmentsWithContent(\"},{\"line\":68,\"text\":\" self::CONTENT_TYPE,\"},{\"line\":74,\"text\":\" throw new \\\\RuntimeException('No screenshot attachment was associated.');\"},{\"line\":77,\"text\":\" $meta = \\\\XF::em()->find('Gram\\\\Support:AttachmentMeta', $attachmentId);\"},{\"line\":80,\"text\":\" $meta = \\\\XF::em()->create('Gram\\\\Support:AttachmentMeta');\"},{\"line\":81,\"text\":\" $meta->attachment_id = $attachmentId;\"}],\"path\":\"Service/GuestScreenshotService.php\",\"sha256\":\"9c0cbf49c4fca5a632a651a288063bc63f9a7ef85f04b32c96b96dd8c9e13e02\"},{\"bytes\":955,\"hit_count\":7,\"hits\":[{\"line\":5,\"text\":\"use Gram\\\\Support\\\\Entity\\\\Ticket;\"},{\"line\":8,\"text\":\"final class GuestTicketCreateAttachmentFlow\"},{\"line\":10,\"text\":\" private GuestScreenshotService $screenshots;\"},{\"line\":14,\"text\":\" $this->screenshots = new GuestScreenshotService();\"},{\"line\":31,\"text\":\" int $attachmentId\"},{\"line\":34,\"text\":\" if (!$upload || $attachmentId < 1)\"},{\"line\":42,\"text\":\" $attachmentId,\"}],\"path\":\"Service/GuestTicketCreateAttachmentFlow.php\",\"sha256\":\"8f4bf8ed6fa0244e6195d7f91bdbdfd0bc7c9ec7d88b1fe5111377a68b8c0266\"},{\"bytes\":5008,\"hit_count\":1,\"hits\":[{\"line\":5,\"text\":\"use Gram\\\\Support\\\\Entity\\\\Ticket;\"}],\"path\":\"Service/Ticket/Creator.php\",\"sha256\":\"7a84cd77761a7943495f9d3ef11269987f85265170ad6cf927a1661b8bf0a99a\"},{\"bytes\":2243,\"hit_count\":1,\"hits\":[{\"line\":5,\"text\":\"use Gram\\\\Support\\\\Entity\\\\Ticket;\"}],\"path\":\"Service/Ticket/Reply.php\",\"sha256\":\"482571a2ccf07a3c8672f34940243264a8271ef8c3cbc4fadbb46112afd36830\"},{\"bytes\":6301,\"hit_count\":5,\"hits\":[{\"line\":18,\"text\":\" $sm->createTable('xf_gram_support_ticket', function($table) {\"},{\"line\":68,\"text\":\" $sm->createTable('xf_gram_support_attachment_meta', function($table) {\"},{\"line\":69,\"text\":\" $table->addColumn('attachment_id', 'int')->unsigned();\"},{\"line\":74,\"text\":\" $table->addPrimaryKey('attachment_id');\"},{\"line\":107,\"text\":\" foreach (['xf_gram_support_attachment_meta','xf_gram_support_delivery','xf_gram_support_rate_limit','xf_gram_support_event','xf_gram_support_message','xf_gram_support_ticket'] as $name) {\"}],\"path\":\"Setup.php\",\"sha256\":\"4977f90ec0444e2e3a1e4ee9b79a4e88098c5a3ae37b30d63e77cff2e1fcb971\"},{\"bytes\":212,\"hit_count\":3,\"hits\":[{\"line\":2,\"text\":\"\"},{\"line\":3,\"text\":\" Gram\\\\Support\\\\Attachment\\\\TicketHandler\"},{\"line\":4,\"text\":\"\"}],\"path\":\"_data/content_type_fields.xml\",\"sha256\":\"6f9760bc6cc3c78aaec3a1ad68bcbc180d6cd4d2ef30830a4dc3b7b500a0cc97\"},{\"bytes\":9117,\"hit_count\":1,\"hits\":[{\"line\":39,\"text\":\" \\u0412\\u043b\\u043e\\u0436\\u0435\\u043d\\u0438\\u044f\"}],\"path\":\"_data/phrases.xml\",\"sha256\":\"ea6e84de301145312758285cfcd63ee4c12b8e921877bcde15c17dd4c115c434\"},{\"bytes\":26547,\"hit_count\":12,\"hits\":[{\"line\":628,\"text\":\"\\t// access state, internal notes, attachments or staff-only information.\"},{\"line\":688,\"text\":\"<xf:if is=\\\"$ticket.Attachments is not empty\\\">\"},{\"line\":691,\"text\":\"\\t\\t\\t<h3 class=\\\"block-minorHeader\\\">{{ phrase('gram_support_attachments') }}</h3>\"},{\"line\":693,\"text\":\"\\t\\t\\t\\t<xf:foreach loop=\\\"$ticket.Attachments\\\" value=\\\"$attachment\\\">\"},{\"line\":695,\"text\":\"\\t\\t\\t\\t\\t\\t<a href=\\\"{{ link('attachments', $attachment) }}\\\">{$attachment.filename}</a>\"},{\"line\":732,\"text\":\"