From 928950220f894301816013ad13d77035c094b65d Mon Sep 17 00:00:00 2001 From: homelab-runtime-publisher Date: Fri, 18 Sep 2026 01:33:05 +0000 Subject: [PATCH] runtime: publish SUPPORT-260918-GRAM-XF-CODEVIPE-NATIVE-RESUME-SCHEMA-RCA-513R3R3 --- ...VIPE-NATIVE-RESUME-SCHEMA-RCA-513R3R3.json | 38 ++++++++++++++++++ ...EVIPE-NATIVE-RESUME-SCHEMA-RCA-513R3R3.txt | 40 +++++++++++++++++++ runtime/latest.json | 16 ++++---- runtime/latest.txt | 20 +++++----- 4 files changed, 96 insertions(+), 18 deletions(-) create mode 100644 runtime/history/SUPPORT-260918-GRAM-XF-CODEVIPE-NATIVE-RESUME-SCHEMA-RCA-513R3R3.json create mode 100644 runtime/history/SUPPORT-260918-GRAM-XF-CODEVIPE-NATIVE-RESUME-SCHEMA-RCA-513R3R3.txt diff --git a/runtime/history/SUPPORT-260918-GRAM-XF-CODEVIPE-NATIVE-RESUME-SCHEMA-RCA-513R3R3.json b/runtime/history/SUPPORT-260918-GRAM-XF-CODEVIPE-NATIVE-RESUME-SCHEMA-RCA-513R3R3.json new file mode 100644 index 00000000..ee585491 --- /dev/null +++ b/runtime/history/SUPPORT-260918-GRAM-XF-CODEVIPE-NATIVE-RESUME-SCHEMA-RCA-513R3R3.json @@ -0,0 +1,38 @@ +{ + "schema_version": 1, + "channel": "homelab-runtime", + "command_id": "SUPPORT-260918-GRAM-XF-CODEVIPE-NATIVE-RESUME-SCHEMA-RCA-513R3R3", + "status": "OK", + "rc": 0, + "host": "pve01", + "mode": "read-only", + "component": "gram-support-codevipe-native-resume-schema-rca", + "started_at_utc": "2026-09-18T01:33:03Z", + "finished_at_utc": "2026-09-18T01:33:05Z", + "reference_register_checked": true, + "reference_sha256": "5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66", + "error_register_checked": true, + "error_register_sha256": "3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0", + "command_sha256": "d024725d107ae38e09893a322f7a365399e215a929d3c723a3099129609390bf", + "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": "3356fd66c51344f1c1c25279dd2f3ad70b12040178c3a7513b0aa812b569ae94", + "sanitized_output_sha256": "3356fd66c51344f1c1c25279dd2f3ad70b12040178c3a7513b0aa812b569ae94", + "output_truncated_in_json": false, + "full_sanitized_output_url": "https://git.gram1.ru/.well-known/homelab-runtime/latest.txt", + "output": "GRAM513R3R3_WRAPPER_BEGIN=true\nERROR_REGISTER_CHECK=OK\nREFERENCE_CHECK=OK\nAUTHORITY_CHECK_SCOPE=READABILITY_ONLY_INCIDENTS_NOT_CLOSED\nGRAM513R3R3_SAFE_REPORT={\"artifact\":{\"sha256\":\"2e31f89d3626a83c1211910aa6fd279cc04689b75ba822899952865085cf551e\",\"version_id\":1000120,\"version_string\":\"1.0.0 Alpha 3 Unified Fix 10\",\"setup_tables\":[\"xf_gram_support_ticket\",\"xf_gram_support_message\",\"xf_gram_support_event\",\"xf_gram_support_attachment_meta\",\"xf_gram_support_delivery\",\"xf_gram_support_rate_limit\"],\"setup_sha256\":\"4977f90ec0444e2e3a1e4ee9b79a4e88098c5a3ae37b30d63e77cff2e1fcb971\"},\"codevipe\":{\"ok\":true,\"tables\":{\"xf_gram_support_ticket\":{\"exists\":true,\"rows\":0,\"ddl_sha256\":\"3558077fc70b4453960d1d782998ad498b2d3b12ba587488e8b23785979f7ba8\",\"ddl\":\"CREATE TABLE `xf_gram_support_ticket` (\\n `ticket_id` int(10) unsigned NOT NULL AUTO_INCREMENT,\\n `public_ref` varchar(64) NOT NULL,\\n `site_id` varchar(32) NOT NULL,\\n `user_id` int(10) unsigned NOT NULL DEFAULT 0,\\n `guest_email` varchar(255) NOT NULL DEFAULT '',\\n `guest_access_token_hash` char(64) NOT NULL DEFAULT '',\\n `guest_access_expires` int(10) unsigned NOT NULL DEFAULT 0,\\n `node_id` int(10) unsigned NOT NULL DEFAULT 0,\\n `thread_id` int(10) unsigned NOT NULL DEFAULT 0,\\n `post_id` int(10) unsigned NOT NULL DEFAULT 0,\\n `category` varchar(64) NOT NULL DEFAULT '',\\n `subject` varchar(255) NOT NULL DEFAULT '',\\n `status` varchar(32) NOT NULL DEFAULT 'NEW',\\n `assigned_user_id` int(10) unsigned NOT NULL DEFAULT 0,\\n `created_date` int(10) unsigned NOT NULL DEFAULT 0,\\n `updated_date` int(10) unsigned NOT NULL DEFAULT 0,\\n `resolved_date` int(10) unsigned NOT NULL DEFAULT 0,\\n `context_json` mediumtext NOT NULL,\\n `last_message_id` int(10) unsigned NOT NULL DEFAULT 0,\\n PRIMARY KEY (`ticket_id`),\\n UNIQUE KEY `public_ref` (`public_ref`),\\n KEY `guest_token_hash` (`guest_access_token_hash`),\\n KEY `site_user_updated` (`site_id`,`user_id`,`updated_date`),\\n KEY `site_status_updated` (`site_id`,`status`,`updated_date`)\\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci\"},\"xf_gram_support_message\":{\"exists\":true,\"rows\":0,\"ddl_sha256\":\"a00e534c642179db3018c74060d1aa6cef4dc445dcb801eb847c04d770f8f884\",\"ddl\":\"CREATE TABLE `xf_gram_support_message` (\\n `message_id` int(10) unsigned NOT NULL AUTO_INCREMENT,\\n `ticket_id` int(10) unsigned NOT NULL,\\n `user_id` int(10) unsigned NOT NULL DEFAULT 0,\\n `is_staff` tinyint(3) unsigned NOT NULL DEFAULT 0,\\n `is_internal` tinyint(3) unsigned NOT NULL DEFAULT 0,\\n `message` mediumtext NOT NULL,\\n `message_date` int(10) unsigned NOT NULL DEFAULT 0,\\n PRIMARY KEY (`message_id`),\\n KEY `ticket_date` (`ticket_id`,`message_date`),\\n KEY `ticket_public_date` (`ticket_id`,`is_internal`,`message_date`)\\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci\"},\"xf_gram_support_event\":{\"exists\":true,\"rows\":0,\"ddl_sha256\":\"81b6328dbbcf3f6405891897ba185e29890c675f21d7a2f9caf827c0eddb42da\",\"ddl\":\"CREATE TABLE `xf_gram_support_event` (\\n `event_id` int(10) unsigned NOT NULL AUTO_INCREMENT,\\n `ticket_id` int(10) unsigned NOT NULL,\\n `site_id` varchar(32) NOT NULL,\\n `actor_user_id` int(10) unsigned NOT NULL DEFAULT 0,\\n `event_type` varchar(64) NOT NULL,\\n `event_date` int(10) unsigned NOT NULL DEFAULT 0,\\n `safe_payload_json` mediumtext NOT NULL,\\n PRIMARY KEY (`event_id`),\\n KEY `ticket_date` (`ticket_id`,`event_date`)\\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci\"},\"xf_gram_support_attachment_meta\":{\"exists\":true,\"rows\":0,\"ddl_sha256\":\"3c3d2ce4c5dae793687243dca37f60cd781895818b546a68e227aef9bfc9b6b2\",\"ddl\":\"CREATE TABLE `xf_gram_support_attachment_meta` (\\n `attachment_id` int(10) unsigned NOT NULL,\\n `ticket_id` int(10) unsigned NOT NULL,\\n `message_id` int(10) unsigned NOT NULL DEFAULT 0,\\n `is_internal` tinyint(3) unsigned NOT NULL DEFAULT 0,\\n `created_date` int(10) unsigned NOT NULL DEFAULT 0,\\n PRIMARY KEY (`attachment_id`),\\n KEY `ticket_internal` (`ticket_id`,`is_internal`),\\n KEY `message_id` (`message_id`)\\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci\"},\"xf_gram_support_delivery\":{\"exists\":true,\"rows\":0,\"ddl_sha256\":\"91f068994bdbe4b168ab1c82fa669180f13825e6d1a7f5b9e956ccc872d0410d\",\"ddl\":\"CREATE TABLE `xf_gram_support_delivery` (\\n `delivery_key` char(64) NOT NULL,\\n `event_id` int(10) unsigned NOT NULL,\\n `consumer` varchar(32) NOT NULL,\\n `recipient_key` varchar(96) NOT NULL,\\n `state` varchar(16) NOT NULL DEFAULT 'pending',\\n `lease_expires` int(10) unsigned NOT NULL DEFAULT 0,\\n `attempt_count` int(10) unsigned NOT NULL DEFAULT 0,\\n `last_failure_class` varchar(191) NOT NULL DEFAULT '',\\n `created_date` int(10) unsigned NOT NULL DEFAULT 0,\\n `updated_date` int(10) unsigned NOT NULL DEFAULT 0,\\n `sent_date` int(10) unsigned NOT NULL DEFAULT 0,\\n PRIMARY KEY (`delivery_key`),\\n KEY `event_consumer` (`event_id`,`consumer`),\\n KEY `state_lease` (`state`,`lease_expires`)\\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci\"},\"xf_gram_support_rate_limit\":{\"exists\":true,\"rows\":0,\"ddl_sha256\":\"f2271e20d520a8ba413b2094a4f8f6640395065c7d9c2e4f5b0a74b790d3dd8e\",\"ddl\":\"CREATE TABLE `xf_gram_support_rate_limit` (\\n `rate_key` char(64) NOT NULL,\\n `window_start` int(10) unsigned NOT NULL,\\n `hit_count` int(10) unsigned NOT NULL DEFAULT 0,\\n `updated_date` int(10) unsigned NOT NULL DEFAULT 0,\\n PRIMARY KEY (`rate_key`),\\n KEY `updated_date` (`updated_date`)\\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci\"}},\"addon\":null,\"schema_manager_class\":\"XF\\\\Db\\\\SchemaManager\",\"schema_methods\":{\"createTable\":{\"ok\":true,\"class\":\"XF\\\\Db\\\\SchemaManager\",\"method\":\"createTable\",\"file\":\"SchemaManager.php\",\"start\":187,\"end\":200,\"sha256\":\"be6c143b9b8321148d841530fe0e5f8388b5fa178a96a8a1fe759e8208eb71a4\",\"source\":\"\\tpublic function createTable($tableName, \\\\Closure $toApply)\\n\\t{\\n\\t\\t$create = $this->newTable($tableName);\\n\\n\\t\\ttry\\n\\t\\t{\\n\\t\\t\\t$toApply($create);\\n\\t\\t\\t$create->apply();\\n\\t\\t}\\n\\t\\tcatch (\\\\Exception $e)\\n\\t\\t{\\n\\t\\t\\t$this->handleException($e, $tableName, $create);\\n\\t\\t}\\n\\t}\\n\",\"lines\":[{\"line\":187,\"text\":\"\\tpublic function createTable($tableName, \\\\Closure $toApply)\"},{\"line\":188,\"text\":\"\\t{\"},{\"line\":189,\"text\":\"\\t\\t$create = $this->newTable($tableName);\"},{\"line\":190,\"text\":\"\"},{\"line\":191,\"text\":\"\\t\\ttry\"},{\"line\":192,\"text\":\"\\t\\t{\"},{\"line\":193,\"text\":\"\\t\\t\\t$toApply($create);\"},{\"line\":194,\"text\":\"\\t\\t\\t$create->apply();\"},{\"line\":195,\"text\":\"\\t\\t}\"},{\"line\":196,\"text\":\"\\t\\tcatch (\\\\Exception $e)\"},{\"line\":197,\"text\":\"\\t\\t{\"},{\"line\":198,\"text\":\"\\t\\t\\t$this->handleException($e, $tableName, $create);\"},{\"line\":199,\"text\":\"\\t\\t}\"},{\"line\":200,\"text\":\"\\t}\"}]},\"newTable\":{\"ok\":true,\"class\":\"XF\\\\Db\\\\SchemaManager\",\"method\":\"newTable\",\"file\":\"SchemaManager.php\",\"start\":239,\"end\":242,\"sha256\":\"482ad432f7e1304bb4289a1e56fb600d7dfb3708393ec2fd4d6ceba61f8d61de\",\"source\":\"\\tpublic function newTable($tableName)\\n\\t{\\n\\t\\treturn new Create($this->db, $this, $tableName);\\n\\t}\\n\",\"lines\":[{\"line\":239,\"text\":\"\\tpublic function newTable($tableName)\"},{\"line\":240,\"text\":\"\\t{\"},{\"line\":241,\"text\":\"\\t\\treturn new Create($this->db, $this, $tableName);\"},{\"line\":242,\"text\":\"\\t}\"}]},\"handleException\":{\"ok\":true,\"class\":\"XF\\\\Db\\\\SchemaManager\",\"method\":\"handleException\",\"file\":\"SchemaManager.php\",\"start\":254,\"end\":270,\"sha256\":\"bcfbb554306aeb3c108d447c45183c8d6c2415d91e9e785a9671ea1900dbc103\",\"source\":\"\\tprotected function handleException($exception, $tableName, AbstractDdl $ddl)\\n\\t{\\n\\t\\t// The exception might have some extra useful stuff in it, so include attempt to modify the message directly.\\n\\n\\t\\ttry\\n\\t\\t{\\n\\t\\t\\t$reflectionClass = new \\\\ReflectionClass($exception);\\n\\t\\t\\t$messageProperty = $reflectionClass->getProperty('message');\\n\\t\\t\\t$messageProperty->setAccessible(true);\\n\\t\\t\\t$messageProperty->setValue($exception, $tableName . ': ' . $messageProperty->getValue($exception));\\n\\t\\t}\\n\\t\\tcatch (\\\\ReflectionException $ignored)\\n\\t\\t{\\n\\t\\t}\\n\\n\\t\\tthrow $exception;\\n\\t}\\n\",\"lines\":[{\"line\":254,\"text\":\"\\tprotected function handleException($exception, $tableName, AbstractDdl $ddl)\"},{\"line\":255,\"text\":\"\\t{\"},{\"line\":256,\"text\":\"\\t\\t// The exception might have some extra useful stuff in it, so include attempt to modify the message directly.\"},{\"line\":257,\"text\":\"\"},{\"line\":258,\"text\":\"\\t\\ttry\"},{\"line\":259,\"text\":\"\\t\\t{\"},{\"line\":260,\"text\":\"\\t\\t\\t$reflectionClass = new \\\\ReflectionClass($exception);\"},{\"line\":261,\"text\":\"\\t\\t\\t$messageProperty = $reflectionClass->getProperty('message');\"},{\"line\":262,\"text\":\"\\t\\t\\t$messageProperty->setAccessible(true);\"},{\"line\":263,\"text\":\"\\t\\t\\t$messageProperty->setValue($exception, $tableName . ': ' . $messageProperty->getValue($exception));\"},{\"line\":264,\"text\":\"\\t\\t}\"},{\"line\":265,\"text\":\"\\t\\tcatch (\\\\ReflectionException $ignored)\"},{\"line\":266,\"text\":\"\\t\\t{\"},{\"line\":267,\"text\":\"\\t\\t}\"},{\"line\":268,\"text\":\"\"},{\"line\":269,\"text\":\"\\t\\tthrow $exception;\"},{\"line\":270,\"text\":\"\\t}\"}]},\"alterTable\":{\"ok\":true,\"class\":\"XF\\\\Db\\\\SchemaManager\",\"method\":\"alterTable\",\"file\":\"SchemaManager.php\",\"start\":150,\"end\":163,\"sha256\":\"5e9788e5e9344db7c332d6c7e728a050f83967ac6d9d8a06727d266dcbbcc787\",\"source\":\"\\tpublic function alterTable($tableName, \\\\Closure $toApply)\\n\\t{\\n\\t\\t$alter = $this->newAlter($tableName);\\n\\n\\t\\ttry\\n\\t\\t{\\n\\t\\t\\t$toApply($alter);\\n\\t\\t\\t$alter->apply();\\n\\t\\t}\\n\\t\\tcatch (\\\\Exception $e)\\n\\t\\t{\\n\\t\\t\\t$this->handleException($e, $tableName, $alter);\\n\\t\\t}\\n\\t}\\n\",\"lines\":[{\"line\":150,\"text\":\"\\tpublic function alterTable($tableName, \\\\Closure $toApply)\"},{\"line\":151,\"text\":\"\\t{\"},{\"line\":152,\"text\":\"\\t\\t$alter = $this->newAlter($tableName);\"},{\"line\":153,\"text\":\"\"},{\"line\":154,\"text\":\"\\t\\ttry\"},{\"line\":155,\"text\":\"\\t\\t{\"},{\"line\":156,\"text\":\"\\t\\t\\t$toApply($alter);\"},{\"line\":157,\"text\":\"\\t\\t\\t$alter->apply();\"},{\"line\":158,\"text\":\"\\t\\t}\"},{\"line\":159,\"text\":\"\\t\\tcatch (\\\\Exception $e)\"},{\"line\":160,\"text\":\"\\t\\t{\"},{\"line\":161,\"text\":\"\\t\\t\\t$this->handleException($e, $tableName, $alter);\"},{\"line\":162,\"text\":\"\\t\\t}\"},{\"line\":163,\"text\":\"\\t}\"}]},\"renameTable\":{\"ok\":true,\"class\":\"XF\\\\Db\\\\SchemaManager\",\"method\":\"renameTable\",\"file\":\"SchemaManager.php\",\"start\":169,\"end\":181,\"sha256\":\"c352def9c86f9233a9c629670c5334a436092765a9c121807a21ef536510d7db\",\"source\":\"\\tpublic function renameTable($oldTableName, $newTableName)\\n\\t{\\n\\t\\t$alter = $this->newAlter($oldTableName)->renameTo($newTableName);\\n\\n\\t\\ttry\\n\\t\\t{\\n\\t\\t\\t$alter->apply();\\n\\t\\t}\\n\\t\\tcatch (\\\\Exception $e)\\n\\t\\t{\\n\\t\\t\\t$this->handleException($e, $oldTableName, $alter);\\n\\t\\t}\\n\\t}\\n\",\"lines\":[{\"line\":169,\"text\":\"\\tpublic function renameTable($oldTableName, $newTableName)\"},{\"line\":170,\"text\":\"\\t{\"},{\"line\":171,\"text\":\"\\t\\t$alter = $this->newAlter($oldTableName)->renameTo($newTableName);\"},{\"line\":172,\"text\":\"\"},{\"line\":173,\"text\":\"\\t\\ttry\"},{\"line\":174,\"text\":\"\\t\\t{\"},{\"line\":175,\"text\":\"\\t\\t\\t$alter->apply();\"},{\"line\":176,\"text\":\"\\t\\t}\"},{\"line\":177,\"text\":\"\\t\\tcatch (\\\\Exception $e)\"},{\"line\":178,\"text\":\"\\t\\t{\"},{\"line\":179,\"text\":\"\\t\\t\\t$this->handleException($e, $oldTableName, $alter);\"},{\"line\":180,\"text\":\"\\t\\t}\"},{\"line\":181,\"text\":\"\\t}\"}]},\"tableExists\":{\"ok\":true,\"class\":\"XF\\\\Db\\\\SchemaManager\",\"method\":\"tableExists\",\"file\":\"SchemaManager.php\",\"start\":119,\"end\":124,\"sha256\":\"234d0c64067ebbf246972acbed6d58574c535e2ad78478d529afd97963551070\",\"source\":\"\\tpublic function tableExists($tableName)\\n\\t{\\n\\t\\t$status = $this->getTableStatus($tableName);\\n\\n\\t\\treturn $status ? true : false;\\n\\t}\\n\",\"lines\":[{\"line\":119,\"text\":\"\\tpublic function tableExists($tableName)\"},{\"line\":120,\"text\":\"\\t{\"},{\"line\":121,\"text\":\"\\t\\t$status = $this->getTableStatus($tableName);\"},{\"line\":122,\"text\":\"\"},{\"line\":123,\"text\":\"\\t\\treturn $status ? true : false;\"},{\"line\":124,\"text\":\"\\t}\"}]}},\"table_create_class\":\"XF\\\\Db\\\\Schema\\\\Create\",\"table_create_methods\":{\"apply\":{\"ok\":true,\"class\":\"XF\\\\Db\\\\Schema\\\\Create\",\"method\":\"apply\",\"file\":\"AbstractDdl.php\",\"start\":152,\"end\":162,\"sha256\":\"70bf8158872ac741e410f19c8a3893809f6a4514907495ec2fe6af5204446493\",\"source\":\"\\tpublic function apply()\\n\\t{\\n\\t\\t$queries = $this->getQueries();\\n\\n\\t\\tforeach ($queries AS $query)\\n\\t\\t{\\n\\t\\t\\t$this->db->query($query);\\n\\t\\t}\\n\\n\\t\\treturn $queries;\\n\\t}\\n\",\"lines\":[{\"line\":152,\"text\":\"\\tpublic function apply()\"},{\"line\":153,\"text\":\"\\t{\"},{\"line\":154,\"text\":\"\\t\\t$queries = $this->getQueries();\"},{\"line\":155,\"text\":\"\"},{\"line\":156,\"text\":\"\\t\\tforeach ($queries AS $query)\"},{\"line\":157,\"text\":\"\\t\\t{\"},{\"line\":158,\"text\":\"\\t\\t\\t$this->db->query($query);\"},{\"line\":159,\"text\":\"\\t\\t}\"},{\"line\":160,\"text\":\"\"},{\"line\":161,\"text\":\"\\t\\treturn $queries;\"},{\"line\":162,\"text\":\"\\t}\"}]},\"getQueries\":{\"ok\":true,\"class\":\"XF\\\\Db\\\\Schema\\\\Create\",\"method\":\"getQueries\",\"file\":\"Create.php\",\"start\":26,\"end\":110,\"sha256\":\"86696c181f223784f11bf6591fd070796b316648462933706f2702ca20eff475\",\"source\":\"\\tpublic function getQueries()\\n\\t{\\n\\t\\t$tableName = $this->tableName;\\n\\n\\t\\t$queries = [];\\n\\n\\t\\t$query = 'CREATE TABLE';\\n\\n\\t\\tif ($this->checkExists)\\n\\t\\t{\\n\\t\\t\\t$query .= ' IF NOT EXISTS';\\n\\t\\t}\\n\\t\\telse\\n\\t\\t{\\n\\t\\t\\t$existing = $this->db->getSchemaManager()->getTableStatus($tableName);\\n\\t\\t\\tif ($existing)\\n\\t\\t\\t{\\n\\t\\t\\t\\t$existing = new static($this->db, $this->sm, $tableName);\\n\\t\\t\\t\\t$existing->setDefinition();\\n\\n\\t\\t\\t\\tif ($this->compare($existing))\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t// new table is identical, so just skip it\\n\\t\\t\\t\\t\\treturn [];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\telse if ($this->forceChanges)\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t$conflictName = $tableName . '__conflict';\\n\\t\\t\\t\\t\\tif ($this->sm->tableExists($conflictName))\\n\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t$i = 2;\\n\\t\\t\\t\\t\\t\\twhile ($this->sm->tableExists($conflictName . $i))\\n\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t$i++;\\n\\t\\t\\t\\t\\t\\t}\\n\\n\\t\\t\\t\\t\\t\\t$conflictName .= $i;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t$queries[] = \\\"ALTER TABLE `$tableName` RENAME TO `$conflictName`\\\";\\n\\n\\t\\t\\t\\t\\t$errorMessage = sprintf(\\n\\t\\t\\t\\t\\t\\t\\\"Renamed table %s to %s to avoid schema conflict\\\",\\n\\t\\t\\t\\t\\t\\t$tableName,\\n\\t\\t\\t\\t\\t\\t$conflictName\\n\\t\\t\\t\\t\\t);\\n\\n\\t\\t\\t\\t\\t\\\\XF::logError($errorMessage, true);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\telse\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\tthrow new \\\\LogicException(\\\"$tableName already exists, but the structure does not match.\\\");\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\n\\t\\t$query .= \\\" `$tableName` (\\\\n\\\\t\\\";\\n\\n\\t\\t$tableDefinition = [];\\n\\t\\tforeach ($this->addColumns AS $column)\\n\\t\\t{\\n\\t\\t\\t$tableDefinition[] = $column->getDefinition();\\n\\t\\t}\\n\\t\\tforeach ($this->addIndexes AS $index)\\n\\t\\t{\\n\\t\\t\\t$tableDefinition[$index->getIndexName()] = $index->getDefinition();\\n\\t\\t}\\n\\n\\t\\t$query .= implode(\\\",\\\\n\\\\t\\\", $tableDefinition);\\n\\t\\t$query .= \\\"\\\\n)\\\";\\n\\t\\t$query .= ' ' . $this->db->getSchemaManager()->getTableConfigSql($this->engine ?: null);\\n\\n\\t\\tif ($this->comment)\\n\\t\\t{\\n\\t\\t\\t$query .= ' COMMENT=' . $this->db->quote($this->comment);\\n\\t\\t}\\n\\n\\t\\tif ($this->autoIncrementIndex !== null)\\n\\t\\t{\\n\\t\\t\\t$query .= ' AUTO_INCREMENT=' . $this->autoIncrementIndex;\\n\\t\\t}\\n\\n\\t\\t$queries[] = $query;\\n\\n\\t\\treturn $queries;\\n\\t}\\n\",\"lines\":[{\"line\":26,\"text\":\"\\tpublic function getQueries()\"},{\"line\":27,\"text\":\"\\t{\"},{\"line\":28,\"text\":\"\\t\\t$tableName = $this->tableName;\"},{\"line\":29,\"text\":\"\"},{\"line\":30,\"text\":\"\\t\\t$queries = [];\"},{\"line\":31,\"text\":\"\"},{\"line\":32,\"text\":\"\\t\\t$query = 'CREATE TABLE';\"},{\"line\":33,\"text\":\"\"},{\"line\":34,\"text\":\"\\t\\tif ($this->checkExists)\"},{\"line\":35,\"text\":\"\\t\\t{\"},{\"line\":36,\"text\":\"\\t\\t\\t$query .= ' IF NOT EXISTS';\"},{\"line\":37,\"text\":\"\\t\\t}\"},{\"line\":38,\"text\":\"\\t\\telse\"},{\"line\":39,\"text\":\"\\t\\t{\"},{\"line\":40,\"text\":\"\\t\\t\\t$existing = $this->db->getSchemaManager()->getTableStatus($tableName);\"},{\"line\":41,\"text\":\"\\t\\t\\tif ($existing)\"},{\"line\":42,\"text\":\"\\t\\t\\t{\"},{\"line\":43,\"text\":\"\\t\\t\\t\\t$existing = new static($this->db, $this->sm, $tableName);\"},{\"line\":44,\"text\":\"\\t\\t\\t\\t$existing->setDefinition();\"},{\"line\":45,\"text\":\"\"},{\"line\":46,\"text\":\"\\t\\t\\t\\tif ($this->compare($existing))\"},{\"line\":47,\"text\":\"\\t\\t\\t\\t{\"},{\"line\":48,\"text\":\"\\t\\t\\t\\t\\t// new table is identical, so just skip it\"},{\"line\":49,\"text\":\"\\t\\t\\t\\t\\treturn [];\"},{\"line\":50,\"text\":\"\\t\\t\\t\\t}\"},{\"line\":51,\"text\":\"\\t\\t\\t\\telse if ($this->forceChanges)\"},{\"line\":52,\"text\":\"\\t\\t\\t\\t{\"},{\"line\":53,\"text\":\"\\t\\t\\t\\t\\t$conflictName = $tableName . '__conflict';\"},{\"line\":54,\"text\":\"\\t\\t\\t\\t\\tif ($this->sm->tableExists($conflictName))\"},{\"line\":55,\"text\":\"\\t\\t\\t\\t\\t{\"},{\"line\":56,\"text\":\"\\t\\t\\t\\t\\t\\t$i = 2;\"},{\"line\":57,\"text\":\"\\t\\t\\t\\t\\t\\twhile ($this->sm->tableExists($conflictName . $i))\"},{\"line\":58,\"text\":\"\\t\\t\\t\\t\\t\\t{\"},{\"line\":59,\"text\":\"\\t\\t\\t\\t\\t\\t\\t$i++;\"},{\"line\":60,\"text\":\"\\t\\t\\t\\t\\t\\t}\"},{\"line\":61,\"text\":\"\"},{\"line\":62,\"text\":\"\\t\\t\\t\\t\\t\\t$conflictName .= $i;\"},{\"line\":63,\"text\":\"\\t\\t\\t\\t\\t}\"},{\"line\":64,\"text\":\"\\t\\t\\t\\t\\t$queries[] = \\\"ALTER TABLE `$tableName` RENAME TO `$conflictName`\\\";\"},{\"line\":65,\"text\":\"\"},{\"line\":66,\"text\":\"\\t\\t\\t\\t\\t$errorMessage = sprintf(\"},{\"line\":67,\"text\":\"\\t\\t\\t\\t\\t\\t\\\"Renamed table %s to %s to avoid schema conflict\\\",\"},{\"line\":68,\"text\":\"\\t\\t\\t\\t\\t\\t$tableName,\"},{\"line\":69,\"text\":\"\\t\\t\\t\\t\\t\\t$conflictName\"},{\"line\":70,\"text\":\"\\t\\t\\t\\t\\t);\"},{\"line\":71,\"text\":\"\"},{\"line\":72,\"text\":\"\\t\\t\\t\\t\\t\\\\XF::logError($errorMessage, true);\"},{\"line\":73,\"text\":\"\\t\\t\\t\\t}\"},{\"line\":74,\"text\":\"\\t\\t\\t\\telse\"},{\"line\":75,\"text\":\"\\t\\t\\t\\t{\"},{\"line\":76,\"text\":\"\\t\\t\\t\\t\\tthrow new \\\\LogicException(\\\"$tableName already exists, but the structure does not match.\\\");\"},{\"line\":77,\"text\":\"\\t\\t\\t\\t}\"},{\"line\":78,\"text\":\"\\t\\t\\t}\"},{\"line\":79,\"text\":\"\\t\\t}\"},{\"line\":80,\"text\":\"\"},{\"line\":81,\"text\":\"\\t\\t$query .= \\\" `$tableName` (\\\\n\\\\t\\\";\"},{\"line\":82,\"text\":\"\"},{\"line\":83,\"text\":\"\\t\\t$tableDefinition = [];\"},{\"line\":84,\"text\":\"\\t\\tforeach ($this->addColumns AS $column)\"},{\"line\":85,\"text\":\"\\t\\t{\"},{\"line\":86,\"text\":\"\\t\\t\\t$tableDefinition[] = $column->getDefinition();\"},{\"line\":87,\"text\":\"\\t\\t}\"},{\"line\":88,\"text\":\"\\t\\tforeach ($this->addIndexes AS $index)\"},{\"line\":89,\"text\":\"\\t\\t{\"},{\"line\":90,\"text\":\"\\t\\t\\t$tableDefinition[$index->getIndexName()] = $index->getDefinition();\"},{\"line\":91,\"text\":\"\\t\\t}\"},{\"line\":92,\"text\":\"\"},{\"line\":93,\"text\":\"\\t\\t$query .= implode(\\\",\\\\n\\\\t\\\", $tableDefinition);\"},{\"line\":94,\"text\":\"\\t\\t$query .= \\\"\\\\n)\\\";\"},{\"line\":95,\"text\":\"\\t\\t$query .= ' ' . $this->db->getSchemaManager()->getTableConfigSql($this->engine ?: null);\"},{\"line\":96,\"text\":\"\"},{\"line\":97,\"text\":\"\\t\\tif ($this->comment)\"},{\"line\":98,\"text\":\"\\t\\t{\"},{\"line\":99,\"text\":\"\\t\\t\\t$query .= ' COMMENT=' . $this->db->quote($this->comment);\"},{\"line\":100,\"text\":\"\\t\\t}\"},{\"line\":101,\"text\":\"\"},{\"line\":102,\"text\":\"\\t\\tif ($this->autoIncrementIndex !== null)\"},{\"line\":103,\"text\":\"\\t\\t{\"},{\"line\":104,\"text\":\"\\t\\t\\t$query .= ' AUTO_INCREMENT=' . $this->autoIncrementIndex;\"},{\"line\":105,\"text\":\"\\t\\t}\"},{\"line\":106,\"text\":\"\"},{\"line\":107,\"text\":\"\\t\\t$queries[] = $query;\"},{\"line\":108,\"text\":\"\"},{\"line\":109,\"text\":\"\\t\\treturn $queries;\"},{\"line\":110,\"text\":\"\\t}\"}]},\"getCreateQuery\":{\"ok\":false,\"class\":\"XF\\\\Db\\\\Schema\\\\Create\",\"method\":\"getCreateQuery\",\"error\":\"ReflectionException\"},\"exists\":{\"ok\":false,\"class\":\"XF\\\\Db\\\\Schema\\\\Create\",\"method\":\"exists\",\"error\":\"ReflectionException\"}},\"source_scans\":[{\"file\":\"src/XF/Cli/Command/AddOnActionTrait.php\",\"sha256\":\"265c7bd3e5dbeb5669b52e57fc9c67411261be00e493cc717aa6b5c991421287\",\"hits\":[{\"line\":15,\"text\":\"use XF\\\\AddOn\\\\StepResult;\"},{\"line\":118,\"text\":\"/** @var StepResult $result */\"},{\"line\":131,\"text\":\"$params['step'] = $result->step;\"},{\"line\":219,\"text\":\"'xf:addon-sub-action',\"}]},{\"file\":\"src/XF/Cli/Command/AddOnInstall.php\",\"sha256\":\"2407ad9ae20ca8ac1ca84b456ac2adc537f39c79534da5e258167a4d0df2a54f\",\"hits\":[{\"line\":20,\"text\":\"->setName('xf:addon-install')\"}]},{\"file\":\"src/XF/Cli/Command/AddOnList.php\",\"sha256\":\"3047ffa03d4fa488cb8a53c2f0c8c88edd8372e5804340f72b3fd761b7eff1ea\",\"hits\":[{\"line\":136,\"text\":\"'last_pending_action' => $installed->last_pending_action,\"},{\"line\":198,\"text\":\"$installed->last_pending_action ?: '-',\"}]},{\"file\":\"src/XF/Cli/Command/AddOnSubAction.php\",\"sha256\":\"4cbf315edc17bf5773c624da2d1af076f47dd588398462d657f709d832adbb46\",\"hits\":[{\"line\":18,\"text\":\"->setName('xf:addon-sub-action')\"},{\"line\":19,\"text\":\"->setDescription('Runs a add-on sub-action in a separate process. Do not run directly!')\"},{\"line\":46,\"text\":\"$output->writeln(\\\"Invalid sub-action confirmation key. Run from parent command.\\\");\"}]},{\"file\":\"src/XF/Cli/Command/Import.php\",\"sha256\":\"cbc8b5707e84a1b1293ca00f57dcc91bb0ded0d3810eb976d0b93327c1dd32f5\",\"hits\":[{\"line\":14,\"text\":\"use XF\\\\Import\\\\StepState;\"},{\"line\":39,\"text\":\"'If set, the import will be automatically finalized when the data import step completes.'\"},{\"line\":112,\"text\":\"function ($isComplete, $step, StepState $stepState, $importCompletion) use ($progressIndicator, &$progressStarted)\"},{\"line\":114,\"text\":\"$stepTitle = $stepState->title;\"},{\"line\":115,\"text\":\"if (!$stepTitle)\"},{\"line\":132,\"text\":\"$stepNumberStrlen = strlen((string) $importCompletion['total']);\"},{\"line\":133,\"text\":\"$stepNameStrlen = 25; // just arbitrary for now, but could be based on the strlen of the longest step title\"},{\"line\":135,\"text\":\"$stepInfo = sprintf(\"},{\"line\":136,\"text\":\"\\\"Step %{$stepNumberStrlen}d of %d: %-{$stepNameStrlen}s \\\",\"},{\"line\":139,\"text\":\"$stepTitle\"},{\"line\":142,\"text\":\"if ($stepState->complete)\"},{\"line\":145,\"text\":\"$stepInfo\"},{\"line\":146,\"text\":\". $this->getIntervalString($stepState->startDate, $stepState->completeDate)\"},{\"line\":147,\"text\":\". ' [' . \\\\XF::language()->numberFormat($stepState->imported) . ']'\"},{\"line\":154,\"text\":\"$stepInfo\"},{\"line\":155,\"text\":\". $this->getIntervalString($stepState->startDate, time()) . ' '\"},{\"line\":156,\"text\":\". $stepState->getCompletionOutput()\"}]},{\"file\":\"src/XF/Cli/Command/ImportChildProcess.php\",\"sha256\":\"4018331a7104801b8d7c73c6bf90374e198ed576897a7b4b01e5195c9d5133f9\",\"hits\":[{\"line\":24,\"text\":\"'step',\"},{\"line\":26,\"text\":\"'The name of the step to run.'\"},{\"line\":63,\"text\":\"$step = $input->getArgument('step');\"},{\"line\":67,\"text\":\"if (!$runner->validateChildProcessRun($step, $startAfter, $end, $error))\"},{\"line\":78,\"text\":\"$runner->runChildProcess($step, $startAfter, $end, $messageReceiver);\"}]},{\"file\":\"src/XF/Cli/Command/ImportCommandTrait.php\",\"sha256\":\"a4816d99b66aa795a1558e01dc42169c471af78028e103533326ced8365f970b\",\"hits\":[{\"line\":21,\"text\":\"$totalsTable->setHeaders(['Step', 'Total', 'Time taken']);\"}]},{\"file\":\"src/XF/Cli/Command/ImportFinalize.php\",\"sha256\":\"78b8ed78256f621c461fe11a6b206a3871819c9960660029feb8d76134ecfde8\",\"hits\":[{\"line\":64,\"text\":\"$jobs = $manager->getImporter($session->importerId)->getFinalizeJobs($session->getStepsRun());\"}]},{\"file\":\"src/XF/Cli/Command/Upgrade.php\",\"sha256\":\"9f58a531299befbb84458add55bb9e701fc18cd06f49d5c86c15fd5871af1a61\",\"hits\":[{\"line\":70,\"text\":\". ($lastUpgradeVersion['last_step'] ? \\\" (step $lastUpgradeVersion[last_step])\\\" : '')\"},{\"line\":75,\"text\":\"$upgradeComplete = ($lastUpgradeVersion['version_id'] === \\\\XF::$versionId && !$lastUpgradeVersion['last_step']);\"},{\"line\":104,\"text\":\"$step = 1;\"},{\"line\":106,\"text\":\"if ($lastUpgradeVersion['last_step'])\"},{\"line\":109,\"text\":\"$step = $lastUpgradeVersion['last_step'] + 1;\"},{\"line\":115,\"text\":\"$step = 1;\"},{\"line\":126,\"text\":\"$upgrader->assertValidUpgradeSteps($upgrade);\"},{\"line\":132,\"text\":\"while (method_exists($upgrade, 'step' . $step))\"},{\"line\":136,\"text\":\"$this->outputStatus($output, \\\"Running upgrade to $versionName, step $step ($position)...\\\");\"},{\"line\":140,\"text\":\"$this->outputStatus($output, \\\"Running upgrade to $versionName, step $step...\\\");\"},{\"line\":143,\"text\":\"$result = $upgrade->{'step' . $step}($position, $data, $controller);\"},{\"line\":146,\"text\":\"$this->clearStatus($output, 'This step must be completed via the web interface.');\"},{\"line\":151,\"text\":\"$this->clearStatus($output, \\\"Running upgrade to $versionName, step $step... done.\\\");\"},{\"line\":156,\"text\":\"$upgrader->insertUpgradeLog($runVersionId, $step);\"},{\"line\":158,\"text\":\"$this->clearStatus($output, \\\"Running upgrade to $versionName, step $step... done.\\\");\"},{\"line\":160,\"text\":\"$step++;\"},{\"line\":166,\"text\":\"// stay on the same step\"},{\"line\":172,\"text\":\"$this->clearStatus($output, 'The upgrade step returned an unexpected result.');\"},{\"line\":180,\"text\":\"$step = 1;\"},{\"line\":184,\"text\":\"$output->writeln(['All upgrade steps run up to version ' . \\\\XF::$version . '.', '']);\"}]},{\"file\":\"src/XF/Cli/Command/AddOn/AbstractSetupStep.php\",\"sha256\":\"86ac6e9eda2202a75f3566a6bf20b14b5cc5171a823e0a23de0e66d0e8c0a8b7\",\"hits\":[{\"line\":9,\"text\":\"use XF\\\\AddOn\\\\StepResult;\"},{\"line\":16,\"text\":\"abstract class AbstractSetupStep extends AbstractCommand\"},{\"line\":21,\"text\":\"abstract protected function getStepType();\"},{\"line\":27,\"text\":\"$command = $this->getStepType();\"},{\"line\":30,\"text\":\"->setName('xf-addon:' . $command . '-step')\"},{\"line\":31,\"text\":\"->setDescription('Runs a specific step from the specified add-on Setup class.')\"},{\"line\":60,\"text\":\"$step = $input->getArgument('step');\"},{\"line\":64,\"text\":\"$stepType = $this->getStepType();\"},{\"line\":65,\"text\":\"if ($stepType == 'upgrade')\"},{\"line\":70,\"text\":\"$setup->prepareForAction($stepType);\"},{\"line\":74,\"text\":\"$result = $this->runStep($setup, $output, $stepType, $step, $version, $params);\"},{\"line\":75,\"text\":\"if (!($result instanceof StepResult))\"},{\"line\":77,\"text\":\"$this->clearStatus($output, \\\"Must return a StepResult object.\\\");\"},{\"line\":104,\"text\":\"protected function runStep(AbstractSetup $setup, OutputInterface $output, $stepType, $step, $version = null, array $params = [])\"},{\"line\":106,\"text\":\"$method = $stepType;\"},{\"line\":112,\"text\":\"if ($step)\"},{\"line\":114,\"text\":\"$method .= 'Step' . $step;\"},{\"line\":119,\"text\":\"if ($version && $step)\"},{\"line\":121,\"text\":\"$method .= $version . 'Step' . $step;\"},{\"line\":129,\"text\":\"return new StepResult(true);\"},{\"line\":137,\"text\":\"$result = new StepResult(true);\"},{\"line\":142,\"text\":\"$result = new StepResult(false, $result);\"}]},{\"file\":\"src/XF/Cli/Command/AddOn/Create.php\",\"sha256\":\"4ff8f77caa12327158b9a6ba6ed2ffe85b959011279be5a70a8b3e77f75204f5\",\"hits\":[{\"line\":217,\"text\":\"$question = new ConfirmationQuestion(\\\"Does your Setup need to support running multiple steps? (y/n) \\\");\"},{\"line\":226,\"text\":\"use XF\\\\AddOn\\\\StepRunnerInstallTrait;\"},{\"line\":227,\"text\":\"use XF\\\\AddOn\\\\StepRunnerUninstallTrait;\"},{\"line\":228,\"text\":\"use XF\\\\AddOn\\\\StepRunnerUpgradeTrait;\"},{\"line\":232,\"text\":\"use StepRunnerInstallTrait;\"},{\"line\":233,\"text\":\"use StepRunnerUpgradeTrait;\"},{\"line\":234,\"text\":\"use StepRunnerUninstallTrait;\"},{\"line\":250,\"text\":\"public function install(array \\\\$stepParams = [])\"},{\"line\":255,\"text\":\"public function upgrade(array \\\\$stepParams = [])\"},{\"line\":260,\"text\":\"public function uninstall(array \\\\$stepParams = [])\"},{\"line\":283,\"text\":\"$output->writeln(\\\"If you change your mind, create a file named Setup.php in \\\" . dirname($setupPath) . \\\" which should extend AbstractSetup and optionally use one of the StepRunnerX traits.\\\");\"}]},{\"file\":\"src/XF/Cli/Command/AddOn/InstallStep.php\",\"sha256\":\"5536a7cdaa190b8ddff16e58733a546c3735ae8e55ab4c9d3cf1e1acce615ca2\",\"hits\":[{\"line\":7,\"text\":\"class InstallStep extends AbstractSetupStep\"},{\"line\":9,\"text\":\"protected function getStepType()\"},{\"line\":17,\"text\":\"'step',\"},{\"line\":19,\"text\":\"'The step number to run.'\"}]},{\"file\":\"src/XF/Cli/Command/AddOn/UninstallStep.php\",\"sha256\":\"d69b287acd3ea5c02bf23492e1bdef465fb75f22f00b45acdb4ffafe547260e5\",\"hits\":[{\"line\":7,\"text\":\"class UninstallStep extends AbstractSetupStep\"},{\"line\":9,\"text\":\"protected function getStepType()\"},{\"line\":17,\"text\":\"'step',\"},{\"line\":19,\"text\":\"'The step number to run.'\"}]},{\"file\":\"src/XF/Cli/Command/AddOn/UpgradeStep.php\",\"sha256\":\"51d6bcea38a819ab7a983340112de1b9778ed9efeb0a139f8d0b6c967b4e052f\",\"hits\":[{\"line\":7,\"text\":\"class UpgradeStep extends AbstractSetupStep\"},{\"line\":9,\"text\":\"protected function getStepType()\"},{\"line\":23,\"text\":\"'step',\"},{\"line\":25,\"text\":\"'The step number to run.'\"}]},{\"file\":\"src/XF/Cli/Command/Rebuild/AbstractRebuildCommand.php\",\"sha256\":\"9b019518b8fb2d2e3bf6d281acb57e181c4b48f2acbf654efdc81b87f294c7f4\",\"hits\":[{\"line\":56,\"text\":\"'resume',\"},{\"line\":73,\"text\":\"if ($input->getOption('resume'))\"},{\"line\":81,\"text\":\"$output->writeln(\\\"There are no pending jobs of this type to resume.\\\");\"}]},{\"file\":\"src/XF/Cli/Command/EmbedMetadata/AbstractEmbedMetadataCommand.php\",\"sha256\":\"d58bdc8eb04615e12b7838403db010fb05ff9238203467061fd7f0bb2d6274f9\",\"hits\":[{\"line\":74,\"text\":\"'resume',\"},{\"line\":77,\"text\":\"'Resume an existing pending job instead of starting a new one. Without this flag, re-running the command discards any prior progress and restarts from the beginning.'\"},{\"line\":92,\"text\":\"if ($input->getOption('resume'))\"},{\"line\":100,\"text\":\"$output->writeln(\\\"There are no pending jobs of this type to resume.\\\");\"}]},{\"file\":\"src/XF/Cli/Command/Development/UpgradeStep.php\",\"sha256\":\"6c91e119b41e5d2b83da72f7d37c02ff2f3d6149b7b7974e05ab3539f0e59fd5\",\"hits\":[{\"line\":18,\"text\":\"class UpgradeStep extends AbstractCommand implements CustomAppCommandInterface\"},{\"line\":30,\"text\":\"->setName('xf-dev:upgrade-step')\"},{\"line\":31,\"text\":\"->setDescription('Runs a specific upgrade step from a specified upgrade class.')\"},{\"line\":38,\"text\":\"'step',\"},{\"line\":40,\"text\":\"'The step number to run'\"},{\"line\":54,\"text\":\"$step = $input->getArgument('step');\"},{\"line\":60,\"text\":\"$returnCode = $this->runStep($upgrade, $output, $controller, $step, $position, $data);\"},{\"line\":73,\"text\":\"throw new \\\\LogicException(\\\"Step did not return an expected result\\\");\"},{\"line\":81,\"text\":\"protected function runStep(AbstractUpgrade $upgrade, OutputInterface $output, Upgrade $controller, $step, $position = 0, $data = [])\"},{\"line\":85,\"text\":\"if (!method_exists($upgrade, 'step' . $step))\"},{\"line\":87,\"text\":\"$this->clearStatus($output, \\\"Upgrade to version $versionName does not have a step$step() method.\\\");\"},{\"line\":93,\"text\":\"$this->outputStatus($output, \\\"Running upgrade to $versionName, step $step ($position)...\\\");\"},{\"line\":97,\"text\":\"$this->outputStatus($output, \\\"Running upgrade to $versionName, step $step...\\\");\"},{\"line\":100,\"text\":\"$result = $upgrade->{'step' . $step}($position, $data, $controller);\"},{\"line\":103,\"text\":\"$this->clearStatus($output, \\\"This step must be completed via the web interface.\\\");\"},{\"line\":108,\"text\":\"$this->clearStatus($output, \\\"Running upgrade to $versionName, step $step... done.\\\");\"},{\"line\":113,\"text\":\"// stay on the same step\"},{\"line\":118,\"text\":\"$this->clearStatus($output, \\\"The upgrade step returned an unexpected result.\\\");\"}]},{\"file\":\"src/XF/AddOn/AbstractSetup.php\",\"sha256\":\"6bdd3fe834e15b963a52c9357f54262f2d12f3c7c3686fc31333b549cddf2d88\",\"hits\":[{\"line\":21,\"text\":\"* @param array $stepParams\"},{\"line\":23,\"text\":\"* @return null|StepResult\"},{\"line\":25,\"text\":\"abstract public function install(array $stepParams = []);\"},{\"line\":28,\"text\":\"* @param array $stepParams\"},{\"line\":30,\"text\":\"* @return null|StepResult\"},{\"line\":32,\"text\":\"abstract public function upgrade(array $stepParams = []);\"},{\"line\":35,\"text\":\"* @param array $stepParams\"},{\"line\":37,\"text\":\"* @return null|StepResult\"},{\"line\":39,\"text\":\"abstract public function uninstall(array $stepParams = []);\"}]},{\"file\":\"src/XF/AddOn/AddOn.php\",\"sha256\":\"0e0346a046fff6bde9850cb53e9dc0d0b5379387029dc16925e562fa141ab422\",\"hits\":[{\"line\":346,\"text\":\"$lastAction = $this->installedAddOn->getLastActionStep('install');\"},{\"line\":349,\"text\":\"// we haven't completed the install steps yet, don't consider as installed\"},{\"line\":537,\"text\":\"public function updatePendingAction($action, $step)\"},{\"line\":541,\"text\":\"$this->installedAddOn->fastUpdate('last_pending_action', \\\"$action:$step\\\");\"},{\"line\":549,\"text\":\"$this->installedAddOn->fastUpdate('last_pending_action', null);\"},{\"line\":568,\"text\":\"'last_pending_action' => 'install:0',\"},{\"line\":653,\"text\":\"$installed->last_pending_action = 'uninstall:0';\"}]},{\"file\":\"src/XF/AddOn/StepResult.php\",\"sha256\":\"d486646b6b20370f7c03f473468ecec93e7cea3ef45cca8d72d6fe9b2701f9be\",\"hits\":[{\"line\":5,\"text\":\"class StepResult\"},{\"line\":9,\"text\":\"public $step;\"},{\"line\":12,\"text\":\"public function __construct($complete, array $params = [], $step = null, $version = null)\"},{\"line\":16,\"text\":\"$this->step = $step;\"}]},{\"file\":\"src/XF/AddOn/StepRunnerInstallTrait.php\",\"sha256\":\"1f441b8a3101b97009ae04e62c04e79062a89f1e01a08ae9e07c5e629c76d5f2\",\"hits\":[{\"line\":10,\"text\":\"trait StepRunnerInstallTrait\"},{\"line\":13,\"text\":\"* @param array $stepParams\"},{\"line\":15,\"text\":\"* @return null|StepResult\"},{\"line\":17,\"text\":\"public function install(array $stepParams = [])\"},{\"line\":19,\"text\":\"$stepParams = array_replace([\"},{\"line\":20,\"text\":\"'step' => 0,\"},{\"line\":21,\"text\":\"], $stepParams);\"},{\"line\":23,\"text\":\"$step = $stepParams['step'];\"},{\"line\":24,\"text\":\"if (!$step)\"},{\"line\":26,\"text\":\"$step = $this->getInstallResumeStep();\"},{\"line\":29,\"text\":\"return $this->installStepRunner($step, $stepParams);\"},{\"line\":32,\"text\":\"private function getInstallResumeStep()\"},{\"line\":37,\"text\":\"$lastActionStep = $installedAddOn->getLastActionStep('install');\"},{\"line\":38,\"text\":\"if ($lastActionStep)\"},{\"line\":40,\"text\":\"return $lastActionStep + 1; // this is the last completed step, so resume with the next\"},{\"line\":48,\"text\":\"* @param integer $step\"},{\"line\":49,\"text\":\"* @param array $stepParams\"},{\"line\":51,\"text\":\"* @return null|StepResult\"},{\"line\":53,\"text\":\"private function installStepRunner($step, array $stepParams)\"},{\"line\":55,\"text\":\"$fnPrefix = 'installStep';\"},{\"line\":56,\"text\":\"$fn = $fnPrefix . $step;\"},{\"line\":62,\"text\":\"$result = $this->$fn($stepParams);\"},{\"line\":65,\"text\":\"$result = new StepResult(true);\"},{\"line\":69,\"text\":\"$result = new StepResult(false, $result);\"},{\"line\":72,\"text\":\"if (!($result instanceof StepResult))\"},{\"line\":74,\"text\":\"throw new \\\\LogicException(\\\"Must return a StepResult object\\\");\"},{\"line\":77,\"text\":\"$result->step = $step;\"},{\"line\":81,\"text\":\"$this->addOn->updatePendingAction('install', $result->step);\"},{\"line\":83,\"text\":\"$nextStep = $step + 1;\"},{\"line\":84,\"text\":\"$nextFn = $fnPrefix . $nextStep;\"},{\"line\":90,\"text\":\"$result = new StepResult(false, [], $nextStep);\"}]},{\"file\":\"src/XF/AddOn/StepRunnerUninstallTrait.php\",\"sha256\":\"e58a9ab9c30e3cf3c41a0be392e8c5ac37f744578f7b91f76d663139649c49a9\",\"hits\":[{\"line\":10,\"text\":\"trait StepRunnerUninstallTrait\"},{\"line\":13,\"text\":\"* @param array $stepParams\"},{\"line\":15,\"text\":\"* @return null|StepResult\"},{\"line\":17,\"text\":\"public function uninstall(array $stepParams = [])\"},{\"line\":19,\"text\":\"$stepParams = array_replace([\"},{\"line\":20,\"text\":\"'step' => 0,\"},{\"line\":21,\"text\":\"], $stepParams);\"},{\"line\":23,\"text\":\"$step = $stepParams['step'];\"},{\"line\":24,\"text\":\"if (!$step)\"},{\"line\":26,\"text\":\"$step = $this->getUninstallResumeStep();\"},{\"line\":28,\"text\":\"return $this->uninstallStepRunner($step, $stepParams);\"},{\"line\":31,\"text\":\"private function getUninstallResumeStep()\"},{\"line\":36,\"text\":\"$lastActionStep = $installedAddOn->getLastActionStep('uninstall');\"},{\"line\":37,\"text\":\"if ($lastActionStep)\"},{\"line\":39,\"text\":\"return $lastActionStep + 1; // this is the last completed step, so resume with the next\"},{\"line\":47,\"text\":\"* @param integer $step\"},{\"line\":48,\"text\":\"* @param array $stepParams\"},{\"line\":50,\"text\":\"* @return null|StepResult\"},{\"line\":52,\"text\":\"private function uninstallStepRunner($step, array $stepParams)\"},{\"line\":54,\"text\":\"$fnPrefix = 'uninstallStep';\"},{\"line\":55,\"text\":\"$fn = $fnPrefix . $step;\"},{\"line\":61,\"text\":\"$result = $this->$fn($stepParams);\"},{\"line\":64,\"text\":\"$result = new StepResult(true);\"},{\"line\":68,\"text\":\"$result = new StepResult(false, $result);\"},{\"line\":71,\"text\":\"if (!($result instanceof StepResult))\"},{\"line\":73,\"text\":\"throw new \\\\LogicException(\\\"Must return a StepResult object\\\");\"},{\"line\":76,\"text\":\"$result->step = $step;\"},{\"line\":80,\"text\":\"$this->addOn->updatePendingAction('uninstall', $result->step);\"},{\"line\":82,\"text\":\"$nextStep = $step + 1;\"},{\"line\":83,\"text\":\"$nextFn = $fnPrefix . $nextStep;\"},{\"line\":89,\"text\":\"$result = new StepResult(false, [], $nextStep);\"}]},{\"file\":\"src/XF/AddOn/StepRunnerUpgradeTrait.php\",\"sha256\":\"b61698d9c20f094cc1b704ad48798148fe5843e2dc746592cb2db252b579d1b5\",\"hits\":[{\"line\":10,\"text\":\"trait StepRunnerUpgradeTrait\"},{\"line\":13,\"text\":\"* @param array $stepParams\"},{\"line\":15,\"text\":\"* @return null|StepResult\"},{\"line\":17,\"text\":\"public function upgrade(array $stepParams = [])\"},{\"line\":19,\"text\":\"$stepParams = $this->getStepParams($stepParams);\"},{\"line\":22,\"text\":\"$stepsGrouped = [];\"},{\"line\":27,\"text\":\"if (preg_match('/^upgrade(\\\\d+)Step(\\\\d+)$/', $method->name, $match))\"},{\"line\":30,\"text\":\"$step = intval($match[2]);\"},{\"line\":33,\"text\":\"$stepsGrouped[$versionId][$step] = $step;\"},{\"line\":42,\"text\":\"if (!$stepParams['version_id'])\"},{\"line\":44,\"text\":\"$resume = $this->getUpgradeResumeStep();\"},{\"line\":45,\"text\":\"$stepParams['version_id'] = $resume[0];\"},{\"line\":46,\"text\":\"$stepParams['step'] = $resume[1];\"},{\"line\":49,\"text\":\"$runStep = $stepParams['step'];\"},{\"line\":50,\"text\":\"if (!$runStep)\"},{\"line\":52,\"text\":\"$runStep = 1;\"},{\"line\":60,\"text\":\"if ($versionId >= $stepParams['version_id'])\"},{\"line\":62,\"text\":\"$versionSteps = $stepsGrouped[$versionId];\"},{\"line\":63,\"text\":\"if (isset($versionSteps[$runStep]))\"},{\"line\":65,\"text\":\"if ($versionId != $stepParams['version_id'] || $runStep != $stepParams['step'])\"},{\"line\":67,\"text\":\"// sanity check - don't pass params if we're changing versions or steps\"},{\"line\":68,\"text\":\"$stepParams = [];\"},{\"line\":73,\"text\":\"return $this->upgradeStepRunner($versionId, $runStep, $stepParams, $nextVersionId);\"},{\"line\":76,\"text\":\"// if we hit here, then the step couldn't be found, so move onto the next upgrade\"},{\"line\":77,\"text\":\"$runStep = 1;\"},{\"line\":78,\"text\":\"$stepParams = $this->getStepParams();\"},{\"line\":86,\"text\":\"protected function getStepParams(array $stepParams = [])\"},{\"line\":90,\"text\":\"'step' => 0,\"},{\"line\":91,\"text\":\"], $stepParams);\"},{\"line\":94,\"text\":\"private function getUpgradeResumeStep()\"},{\"line\":97,\"text\":\"$lastActionStep = $installedAddOn->getLastActionStep('upgrade');\"},{\"line\":98,\"text\":\"if ($lastActionStep)\"},{\"line\":100,\"text\":\"$lastActionStep[1]++; // we completed this step, so need to resume with the next\"},{\"line\":101,\"text\":\"return $lastActionStep;\"},{\"line\":109,\"text\":\"* @param integer $runStep\"},{\"line\":110,\"text\":\"* @param array $stepParams\"},{\"line\":113,\"text\":\"* @return null|StepResult\"},{\"line\":115,\"text\":\"private function upgradeStepRunner($runVersion, $runStep, array $stepParams, $nextVersionId)\"},{\"line\":117,\"text\":\"$fnPattern = 'upgrade%dStep%d';\"},{\"line\":118,\"text\":\"$fn = sprintf($fnPattern, $runVersion, $runStep);\"},{\"line\":121,\"text\":\"throw new \\\\LogicException(\\\"Step $fn doesn't exist. Should have been checked earlier.\\\");\"},{\"line\":124,\"text\":\"$result = $this->$fn($stepParams);\"},{\"line\":127,\"text\":\"$result = new StepResult(true);\"},{\"line\":131,\"text\":\"$result = new StepResult(false, $result);\"},{\"line\":134,\"text\":\"if (!($result instanceof StepResult))\"},{\"line\":136,\"text\":\"throw new \\\\LogicException(\\\"Must return a StepResult object\\\");\"},{\"line\":139,\"text\":\"$result->step = $runStep;\"},{\"line\":144,\"text\":\"$this->addOn->updatePendingAction('upgrade', $result->version . ':' . $result->step);\"},{\"line\":146,\"text\":\"$nextStep = $runStep + 1;\"},{\"line\":147,\"text\":\"$nextStepFn = sprintf($fnPattern, $runVersion, $nextStep);\"},{\"line\":148,\"text\":\"if (method_exists($this, $nextStepFn))\"},{\"line\":150,\"text\":\"$result = new StepResult(false, [], $nextStep, $runVersion);\"},{\"line\":166,\"text\":\"$result = new StepResult(false, [], 1, $nextVersionId);\"}]},{\"file\":\"src/XF/AddOn/DataType/AbstractDataType.php\",\"sha256\":\"a4f6ec14e4009be0029548b07272dc77c6ad96f4cca4e067a7d3ea0004126815\",\"hits\":[{\"line\":165,\"text\":\"protected function resume($maxRunTime, $startTime)\"}]}]},\"assessment\":{\"all_six_tables_present\":true,\"all_six_tables_empty\":true,\"duplicate_create_appears_safe\":true,\"native_resume_signal\":true},\"policy\":{\"delete_performed\":false,\"mutation_performed\":false,\"goal\":\"select a no-delete native or bounded bridge install path\"}}\nGRAM513R3R3_DECISION=PASS_NATIVE_RESUME_SCHEMA_RCA\nGRAM513R3R3_NEXT_GATE=READY_FOR_DIRECT_NATIVE_RETRY_CANARY_513R3R4\nHOMELAB_RESULT_CONTRACT={\"version\":1,\"command_id\":\"SUPPORT-260918-GRAM-XF-CODEVIPE-NATIVE-RESUME-SCHEMA-RCA-513R3R3\",\"status\":\"OK\",\"changes_made\":false,\"rollback_started\":false,\"rollback_restored\":null}\n" +} diff --git a/runtime/history/SUPPORT-260918-GRAM-XF-CODEVIPE-NATIVE-RESUME-SCHEMA-RCA-513R3R3.txt b/runtime/history/SUPPORT-260918-GRAM-XF-CODEVIPE-NATIVE-RESUME-SCHEMA-RCA-513R3R3.txt new file mode 100644 index 00000000..a8a41087 --- /dev/null +++ b/runtime/history/SUPPORT-260918-GRAM-XF-CODEVIPE-NATIVE-RESUME-SCHEMA-RCA-513R3R3.txt @@ -0,0 +1,40 @@ +CHAT_OUTPUT_BEGIN +COMMAND_ID=SUPPORT-260918-GRAM-XF-CODEVIPE-NATIVE-RESUME-SCHEMA-RCA-513R3R3 +STATUS=OK +RC=0 +HOST=pve01 +MODE=read-only +COMPONENT=gram-support-codevipe-native-resume-schema-rca +REFERENCE_REGISTER_CHECK=OK +REFERENCE_SHA256=5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66 +ERROR_REGISTER_CHECK=OK +ERROR_REGISTER_SHA256=3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0 +COMMAND_SHA256=d024725d107ae38e09893a322f7a365399e215a929d3c723a3099129609390bf +DUPLICATE_FAILED_COMMAND_BLOCKED=false +EXECUTION_STARTED=true +CHANGE_DECLARED=false +RESULT_CONTRACT_VALID=true +RESULT_CONTRACT_STATUS=NOT_APPLICABLE +RESULT_CONTRACT_ERROR=NONE +COMMAND_RC=0 +CHANGES_MADE=false +ROLLBACK_STARTED=false +ROLLBACK_RESTORED=null +MUTATION_OUTCOME=NO_MUTATION +SANITIZED=yes +SECRETS_INCLUDED=no +PRIVATE_ADDRESSES_INCLUDED=no +RAW_EVIDENCE_SHA256=3356fd66c51344f1c1c25279dd2f3ad70b12040178c3a7513b0aa812b569ae94 +SANITIZED_OUTPUT_SHA256=3356fd66c51344f1c1c25279dd2f3ad70b12040178c3a7513b0aa812b569ae94 +OUTPUT_BEGIN +GRAM513R3R3_WRAPPER_BEGIN=true +ERROR_REGISTER_CHECK=OK +REFERENCE_CHECK=OK +AUTHORITY_CHECK_SCOPE=READABILITY_ONLY_INCIDENTS_NOT_CLOSED +GRAM513R3R3_SAFE_REPORT={"artifact":{"sha256":"2e31f89d3626a83c1211910aa6fd279cc04689b75ba822899952865085cf551e","version_id":1000120,"version_string":"1.0.0 Alpha 3 Unified Fix 10","setup_tables":["xf_gram_support_ticket","xf_gram_support_message","xf_gram_support_event","xf_gram_support_attachment_meta","xf_gram_support_delivery","xf_gram_support_rate_limit"],"setup_sha256":"4977f90ec0444e2e3a1e4ee9b79a4e88098c5a3ae37b30d63e77cff2e1fcb971"},"codevipe":{"ok":true,"tables":{"xf_gram_support_ticket":{"exists":true,"rows":0,"ddl_sha256":"3558077fc70b4453960d1d782998ad498b2d3b12ba587488e8b23785979f7ba8","ddl":"CREATE TABLE `xf_gram_support_ticket` (\n `ticket_id` int(10) unsigned NOT NULL AUTO_INCREMENT,\n `public_ref` varchar(64) NOT NULL,\n `site_id` varchar(32) NOT NULL,\n `user_id` int(10) unsigned NOT NULL DEFAULT 0,\n `guest_email` varchar(255) NOT NULL DEFAULT '',\n `guest_access_token_hash` char(64) NOT NULL DEFAULT '',\n `guest_access_expires` int(10) unsigned NOT NULL DEFAULT 0,\n `node_id` int(10) unsigned NOT NULL DEFAULT 0,\n `thread_id` int(10) unsigned NOT NULL DEFAULT 0,\n `post_id` int(10) unsigned NOT NULL DEFAULT 0,\n `category` varchar(64) NOT NULL DEFAULT '',\n `subject` varchar(255) NOT NULL DEFAULT '',\n `status` varchar(32) NOT NULL DEFAULT 'NEW',\n `assigned_user_id` int(10) unsigned NOT NULL DEFAULT 0,\n `created_date` int(10) unsigned NOT NULL DEFAULT 0,\n `updated_date` int(10) unsigned NOT NULL DEFAULT 0,\n `resolved_date` int(10) unsigned NOT NULL DEFAULT 0,\n `context_json` mediumtext NOT NULL,\n `last_message_id` int(10) unsigned NOT NULL DEFAULT 0,\n PRIMARY KEY (`ticket_id`),\n UNIQUE KEY `public_ref` (`public_ref`),\n KEY `guest_token_hash` (`guest_access_token_hash`),\n KEY `site_user_updated` (`site_id`,`user_id`,`updated_date`),\n KEY `site_status_updated` (`site_id`,`status`,`updated_date`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci"},"xf_gram_support_message":{"exists":true,"rows":0,"ddl_sha256":"a00e534c642179db3018c74060d1aa6cef4dc445dcb801eb847c04d770f8f884","ddl":"CREATE TABLE `xf_gram_support_message` (\n `message_id` int(10) unsigned NOT NULL AUTO_INCREMENT,\n `ticket_id` int(10) unsigned NOT NULL,\n `user_id` int(10) unsigned NOT NULL DEFAULT 0,\n `is_staff` tinyint(3) unsigned NOT NULL DEFAULT 0,\n `is_internal` tinyint(3) unsigned NOT NULL DEFAULT 0,\n `message` mediumtext NOT NULL,\n `message_date` int(10) unsigned NOT NULL DEFAULT 0,\n PRIMARY KEY (`message_id`),\n KEY `ticket_date` (`ticket_id`,`message_date`),\n KEY `ticket_public_date` (`ticket_id`,`is_internal`,`message_date`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci"},"xf_gram_support_event":{"exists":true,"rows":0,"ddl_sha256":"81b6328dbbcf3f6405891897ba185e29890c675f21d7a2f9caf827c0eddb42da","ddl":"CREATE TABLE `xf_gram_support_event` (\n `event_id` int(10) unsigned NOT NULL AUTO_INCREMENT,\n `ticket_id` int(10) unsigned NOT NULL,\n `site_id` varchar(32) NOT NULL,\n `actor_user_id` int(10) unsigned NOT NULL DEFAULT 0,\n `event_type` varchar(64) NOT NULL,\n `event_date` int(10) unsigned NOT NULL DEFAULT 0,\n `safe_payload_json` mediumtext NOT NULL,\n PRIMARY KEY (`event_id`),\n KEY `ticket_date` (`ticket_id`,`event_date`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci"},"xf_gram_support_attachment_meta":{"exists":true,"rows":0,"ddl_sha256":"3c3d2ce4c5dae793687243dca37f60cd781895818b546a68e227aef9bfc9b6b2","ddl":"CREATE TABLE `xf_gram_support_attachment_meta` (\n `attachment_id` int(10) unsigned NOT NULL,\n `ticket_id` int(10) unsigned NOT NULL,\n `message_id` int(10) unsigned NOT NULL DEFAULT 0,\n `is_internal` tinyint(3) unsigned NOT NULL DEFAULT 0,\n `created_date` int(10) unsigned NOT NULL DEFAULT 0,\n PRIMARY KEY (`attachment_id`),\n KEY `ticket_internal` (`ticket_id`,`is_internal`),\n KEY `message_id` (`message_id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci"},"xf_gram_support_delivery":{"exists":true,"rows":0,"ddl_sha256":"91f068994bdbe4b168ab1c82fa669180f13825e6d1a7f5b9e956ccc872d0410d","ddl":"CREATE TABLE `xf_gram_support_delivery` (\n `delivery_key` char(64) NOT NULL,\n `event_id` int(10) unsigned NOT NULL,\n `consumer` varchar(32) NOT NULL,\n `recipient_key` varchar(96) NOT NULL,\n `state` varchar(16) NOT NULL DEFAULT 'pending',\n `lease_expires` int(10) unsigned NOT NULL DEFAULT 0,\n `attempt_count` int(10) unsigned NOT NULL DEFAULT 0,\n `last_failure_class` varchar(191) NOT NULL DEFAULT '',\n `created_date` int(10) unsigned NOT NULL DEFAULT 0,\n `updated_date` int(10) unsigned NOT NULL DEFAULT 0,\n `sent_date` int(10) unsigned NOT NULL DEFAULT 0,\n PRIMARY KEY (`delivery_key`),\n KEY `event_consumer` (`event_id`,`consumer`),\n KEY `state_lease` (`state`,`lease_expires`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci"},"xf_gram_support_rate_limit":{"exists":true,"rows":0,"ddl_sha256":"f2271e20d520a8ba413b2094a4f8f6640395065c7d9c2e4f5b0a74b790d3dd8e","ddl":"CREATE TABLE `xf_gram_support_rate_limit` (\n `rate_key` char(64) NOT NULL,\n `window_start` int(10) unsigned NOT NULL,\n `hit_count` int(10) unsigned NOT NULL DEFAULT 0,\n `updated_date` int(10) unsigned NOT NULL DEFAULT 0,\n PRIMARY KEY (`rate_key`),\n KEY `updated_date` (`updated_date`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci"}},"addon":null,"schema_manager_class":"XF\\Db\\SchemaManager","schema_methods":{"createTable":{"ok":true,"class":"XF\\Db\\SchemaManager","method":"createTable","file":"SchemaManager.php","start":187,"end":200,"sha256":"be6c143b9b8321148d841530fe0e5f8388b5fa178a96a8a1fe759e8208eb71a4","source":"\tpublic function createTable($tableName, \\Closure $toApply)\n\t{\n\t\t$create = $this->newTable($tableName);\n\n\t\ttry\n\t\t{\n\t\t\t$toApply($create);\n\t\t\t$create->apply();\n\t\t}\n\t\tcatch (\\Exception $e)\n\t\t{\n\t\t\t$this->handleException($e, $tableName, $create);\n\t\t}\n\t}\n","lines":[{"line":187,"text":"\tpublic function createTable($tableName, \\Closure $toApply)"},{"line":188,"text":"\t{"},{"line":189,"text":"\t\t$create = $this->newTable($tableName);"},{"line":190,"text":""},{"line":191,"text":"\t\ttry"},{"line":192,"text":"\t\t{"},{"line":193,"text":"\t\t\t$toApply($create);"},{"line":194,"text":"\t\t\t$create->apply();"},{"line":195,"text":"\t\t}"},{"line":196,"text":"\t\tcatch (\\Exception $e)"},{"line":197,"text":"\t\t{"},{"line":198,"text":"\t\t\t$this->handleException($e, $tableName, $create);"},{"line":199,"text":"\t\t}"},{"line":200,"text":"\t}"}]},"newTable":{"ok":true,"class":"XF\\Db\\SchemaManager","method":"newTable","file":"SchemaManager.php","start":239,"end":242,"sha256":"482ad432f7e1304bb4289a1e56fb600d7dfb3708393ec2fd4d6ceba61f8d61de","source":"\tpublic function newTable($tableName)\n\t{\n\t\treturn new Create($this->db, $this, $tableName);\n\t}\n","lines":[{"line":239,"text":"\tpublic function newTable($tableName)"},{"line":240,"text":"\t{"},{"line":241,"text":"\t\treturn new Create($this->db, $this, $tableName);"},{"line":242,"text":"\t}"}]},"handleException":{"ok":true,"class":"XF\\Db\\SchemaManager","method":"handleException","file":"SchemaManager.php","start":254,"end":270,"sha256":"bcfbb554306aeb3c108d447c45183c8d6c2415d91e9e785a9671ea1900dbc103","source":"\tprotected function handleException($exception, $tableName, AbstractDdl $ddl)\n\t{\n\t\t// The exception might have some extra useful stuff in it, so include attempt to modify the message directly.\n\n\t\ttry\n\t\t{\n\t\t\t$reflectionClass = new \\ReflectionClass($exception);\n\t\t\t$messageProperty = $reflectionClass->getProperty('message');\n\t\t\t$messageProperty->setAccessible(true);\n\t\t\t$messageProperty->setValue($exception, $tableName . ': ' . $messageProperty->getValue($exception));\n\t\t}\n\t\tcatch (\\ReflectionException $ignored)\n\t\t{\n\t\t}\n\n\t\tthrow $exception;\n\t}\n","lines":[{"line":254,"text":"\tprotected function handleException($exception, $tableName, AbstractDdl $ddl)"},{"line":255,"text":"\t{"},{"line":256,"text":"\t\t// The exception might have some extra useful stuff in it, so include attempt to modify the message directly."},{"line":257,"text":""},{"line":258,"text":"\t\ttry"},{"line":259,"text":"\t\t{"},{"line":260,"text":"\t\t\t$reflectionClass = new \\ReflectionClass($exception);"},{"line":261,"text":"\t\t\t$messageProperty = $reflectionClass->getProperty('message');"},{"line":262,"text":"\t\t\t$messageProperty->setAccessible(true);"},{"line":263,"text":"\t\t\t$messageProperty->setValue($exception, $tableName . ': ' . $messageProperty->getValue($exception));"},{"line":264,"text":"\t\t}"},{"line":265,"text":"\t\tcatch (\\ReflectionException $ignored)"},{"line":266,"text":"\t\t{"},{"line":267,"text":"\t\t}"},{"line":268,"text":""},{"line":269,"text":"\t\tthrow $exception;"},{"line":270,"text":"\t}"}]},"alterTable":{"ok":true,"class":"XF\\Db\\SchemaManager","method":"alterTable","file":"SchemaManager.php","start":150,"end":163,"sha256":"5e9788e5e9344db7c332d6c7e728a050f83967ac6d9d8a06727d266dcbbcc787","source":"\tpublic function alterTable($tableName, \\Closure $toApply)\n\t{\n\t\t$alter = $this->newAlter($tableName);\n\n\t\ttry\n\t\t{\n\t\t\t$toApply($alter);\n\t\t\t$alter->apply();\n\t\t}\n\t\tcatch (\\Exception $e)\n\t\t{\n\t\t\t$this->handleException($e, $tableName, $alter);\n\t\t}\n\t}\n","lines":[{"line":150,"text":"\tpublic function alterTable($tableName, \\Closure $toApply)"},{"line":151,"text":"\t{"},{"line":152,"text":"\t\t$alter = $this->newAlter($tableName);"},{"line":153,"text":""},{"line":154,"text":"\t\ttry"},{"line":155,"text":"\t\t{"},{"line":156,"text":"\t\t\t$toApply($alter);"},{"line":157,"text":"\t\t\t$alter->apply();"},{"line":158,"text":"\t\t}"},{"line":159,"text":"\t\tcatch (\\Exception $e)"},{"line":160,"text":"\t\t{"},{"line":161,"text":"\t\t\t$this->handleException($e, $tableName, $alter);"},{"line":162,"text":"\t\t}"},{"line":163,"text":"\t}"}]},"renameTable":{"ok":true,"class":"XF\\Db\\SchemaManager","method":"renameTable","file":"SchemaManager.php","start":169,"end":181,"sha256":"c352def9c86f9233a9c629670c5334a436092765a9c121807a21ef536510d7db","source":"\tpublic function renameTable($oldTableName, $newTableName)\n\t{\n\t\t$alter = $this->newAlter($oldTableName)->renameTo($newTableName);\n\n\t\ttry\n\t\t{\n\t\t\t$alter->apply();\n\t\t}\n\t\tcatch (\\Exception $e)\n\t\t{\n\t\t\t$this->handleException($e, $oldTableName, $alter);\n\t\t}\n\t}\n","lines":[{"line":169,"text":"\tpublic function renameTable($oldTableName, $newTableName)"},{"line":170,"text":"\t{"},{"line":171,"text":"\t\t$alter = $this->newAlter($oldTableName)->renameTo($newTableName);"},{"line":172,"text":""},{"line":173,"text":"\t\ttry"},{"line":174,"text":"\t\t{"},{"line":175,"text":"\t\t\t$alter->apply();"},{"line":176,"text":"\t\t}"},{"line":177,"text":"\t\tcatch (\\Exception $e)"},{"line":178,"text":"\t\t{"},{"line":179,"text":"\t\t\t$this->handleException($e, $oldTableName, $alter);"},{"line":180,"text":"\t\t}"},{"line":181,"text":"\t}"}]},"tableExists":{"ok":true,"class":"XF\\Db\\SchemaManager","method":"tableExists","file":"SchemaManager.php","start":119,"end":124,"sha256":"234d0c64067ebbf246972acbed6d58574c535e2ad78478d529afd97963551070","source":"\tpublic function tableExists($tableName)\n\t{\n\t\t$status = $this->getTableStatus($tableName);\n\n\t\treturn $status ? true : false;\n\t}\n","lines":[{"line":119,"text":"\tpublic function tableExists($tableName)"},{"line":120,"text":"\t{"},{"line":121,"text":"\t\t$status = $this->getTableStatus($tableName);"},{"line":122,"text":""},{"line":123,"text":"\t\treturn $status ? true : false;"},{"line":124,"text":"\t}"}]}},"table_create_class":"XF\\Db\\Schema\\Create","table_create_methods":{"apply":{"ok":true,"class":"XF\\Db\\Schema\\Create","method":"apply","file":"AbstractDdl.php","start":152,"end":162,"sha256":"70bf8158872ac741e410f19c8a3893809f6a4514907495ec2fe6af5204446493","source":"\tpublic function apply()\n\t{\n\t\t$queries = $this->getQueries();\n\n\t\tforeach ($queries AS $query)\n\t\t{\n\t\t\t$this->db->query($query);\n\t\t}\n\n\t\treturn $queries;\n\t}\n","lines":[{"line":152,"text":"\tpublic function apply()"},{"line":153,"text":"\t{"},{"line":154,"text":"\t\t$queries = $this->getQueries();"},{"line":155,"text":""},{"line":156,"text":"\t\tforeach ($queries AS $query)"},{"line":157,"text":"\t\t{"},{"line":158,"text":"\t\t\t$this->db->query($query);"},{"line":159,"text":"\t\t}"},{"line":160,"text":""},{"line":161,"text":"\t\treturn $queries;"},{"line":162,"text":"\t}"}]},"getQueries":{"ok":true,"class":"XF\\Db\\Schema\\Create","method":"getQueries","file":"Create.php","start":26,"end":110,"sha256":"86696c181f223784f11bf6591fd070796b316648462933706f2702ca20eff475","source":"\tpublic function getQueries()\n\t{\n\t\t$tableName = $this->tableName;\n\n\t\t$queries = [];\n\n\t\t$query = 'CREATE TABLE';\n\n\t\tif ($this->checkExists)\n\t\t{\n\t\t\t$query .= ' IF NOT EXISTS';\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$existing = $this->db->getSchemaManager()->getTableStatus($tableName);\n\t\t\tif ($existing)\n\t\t\t{\n\t\t\t\t$existing = new static($this->db, $this->sm, $tableName);\n\t\t\t\t$existing->setDefinition();\n\n\t\t\t\tif ($this->compare($existing))\n\t\t\t\t{\n\t\t\t\t\t// new table is identical, so just skip it\n\t\t\t\t\treturn [];\n\t\t\t\t}\n\t\t\t\telse if ($this->forceChanges)\n\t\t\t\t{\n\t\t\t\t\t$conflictName = $tableName . '__conflict';\n\t\t\t\t\tif ($this->sm->tableExists($conflictName))\n\t\t\t\t\t{\n\t\t\t\t\t\t$i = 2;\n\t\t\t\t\t\twhile ($this->sm->tableExists($conflictName . $i))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$i++;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t$conflictName .= $i;\n\t\t\t\t\t}\n\t\t\t\t\t$queries[] = \"ALTER TABLE `$tableName` RENAME TO `$conflictName`\";\n\n\t\t\t\t\t$errorMessage = sprintf(\n\t\t\t\t\t\t\"Renamed table %s to %s to avoid schema conflict\",\n\t\t\t\t\t\t$tableName,\n\t\t\t\t\t\t$conflictName\n\t\t\t\t\t);\n\n\t\t\t\t\t\\XF::logError($errorMessage, true);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tthrow new \\LogicException(\"$tableName already exists, but the structure does not match.\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t$query .= \" `$tableName` (\\n\\t\";\n\n\t\t$tableDefinition = [];\n\t\tforeach ($this->addColumns AS $column)\n\t\t{\n\t\t\t$tableDefinition[] = $column->getDefinition();\n\t\t}\n\t\tforeach ($this->addIndexes AS $index)\n\t\t{\n\t\t\t$tableDefinition[$index->getIndexName()] = $index->getDefinition();\n\t\t}\n\n\t\t$query .= implode(\",\\n\\t\", $tableDefinition);\n\t\t$query .= \"\\n)\";\n\t\t$query .= ' ' . $this->db->getSchemaManager()->getTableConfigSql($this->engine ?: null);\n\n\t\tif ($this->comment)\n\t\t{\n\t\t\t$query .= ' COMMENT=' . $this->db->quote($this->comment);\n\t\t}\n\n\t\tif ($this->autoIncrementIndex !== null)\n\t\t{\n\t\t\t$query .= ' AUTO_INCREMENT=' . $this->autoIncrementIndex;\n\t\t}\n\n\t\t$queries[] = $query;\n\n\t\treturn $queries;\n\t}\n","lines":[{"line":26,"text":"\tpublic function getQueries()"},{"line":27,"text":"\t{"},{"line":28,"text":"\t\t$tableName = $this->tableName;"},{"line":29,"text":""},{"line":30,"text":"\t\t$queries = [];"},{"line":31,"text":""},{"line":32,"text":"\t\t$query = 'CREATE TABLE';"},{"line":33,"text":""},{"line":34,"text":"\t\tif ($this->checkExists)"},{"line":35,"text":"\t\t{"},{"line":36,"text":"\t\t\t$query .= ' IF NOT EXISTS';"},{"line":37,"text":"\t\t}"},{"line":38,"text":"\t\telse"},{"line":39,"text":"\t\t{"},{"line":40,"text":"\t\t\t$existing = $this->db->getSchemaManager()->getTableStatus($tableName);"},{"line":41,"text":"\t\t\tif ($existing)"},{"line":42,"text":"\t\t\t{"},{"line":43,"text":"\t\t\t\t$existing = new static($this->db, $this->sm, $tableName);"},{"line":44,"text":"\t\t\t\t$existing->setDefinition();"},{"line":45,"text":""},{"line":46,"text":"\t\t\t\tif ($this->compare($existing))"},{"line":47,"text":"\t\t\t\t{"},{"line":48,"text":"\t\t\t\t\t// new table is identical, so just skip it"},{"line":49,"text":"\t\t\t\t\treturn [];"},{"line":50,"text":"\t\t\t\t}"},{"line":51,"text":"\t\t\t\telse if ($this->forceChanges)"},{"line":52,"text":"\t\t\t\t{"},{"line":53,"text":"\t\t\t\t\t$conflictName = $tableName . '__conflict';"},{"line":54,"text":"\t\t\t\t\tif ($this->sm->tableExists($conflictName))"},{"line":55,"text":"\t\t\t\t\t{"},{"line":56,"text":"\t\t\t\t\t\t$i = 2;"},{"line":57,"text":"\t\t\t\t\t\twhile ($this->sm->tableExists($conflictName . $i))"},{"line":58,"text":"\t\t\t\t\t\t{"},{"line":59,"text":"\t\t\t\t\t\t\t$i++;"},{"line":60,"text":"\t\t\t\t\t\t}"},{"line":61,"text":""},{"line":62,"text":"\t\t\t\t\t\t$conflictName .= $i;"},{"line":63,"text":"\t\t\t\t\t}"},{"line":64,"text":"\t\t\t\t\t$queries[] = \"ALTER TABLE `$tableName` RENAME TO `$conflictName`\";"},{"line":65,"text":""},{"line":66,"text":"\t\t\t\t\t$errorMessage = sprintf("},{"line":67,"text":"\t\t\t\t\t\t\"Renamed table %s to %s to avoid schema conflict\","},{"line":68,"text":"\t\t\t\t\t\t$tableName,"},{"line":69,"text":"\t\t\t\t\t\t$conflictName"},{"line":70,"text":"\t\t\t\t\t);"},{"line":71,"text":""},{"line":72,"text":"\t\t\t\t\t\\XF::logError($errorMessage, true);"},{"line":73,"text":"\t\t\t\t}"},{"line":74,"text":"\t\t\t\telse"},{"line":75,"text":"\t\t\t\t{"},{"line":76,"text":"\t\t\t\t\tthrow new \\LogicException(\"$tableName already exists, but the structure does not match.\");"},{"line":77,"text":"\t\t\t\t}"},{"line":78,"text":"\t\t\t}"},{"line":79,"text":"\t\t}"},{"line":80,"text":""},{"line":81,"text":"\t\t$query .= \" `$tableName` (\\n\\t\";"},{"line":82,"text":""},{"line":83,"text":"\t\t$tableDefinition = [];"},{"line":84,"text":"\t\tforeach ($this->addColumns AS $column)"},{"line":85,"text":"\t\t{"},{"line":86,"text":"\t\t\t$tableDefinition[] = $column->getDefinition();"},{"line":87,"text":"\t\t}"},{"line":88,"text":"\t\tforeach ($this->addIndexes AS $index)"},{"line":89,"text":"\t\t{"},{"line":90,"text":"\t\t\t$tableDefinition[$index->getIndexName()] = $index->getDefinition();"},{"line":91,"text":"\t\t}"},{"line":92,"text":""},{"line":93,"text":"\t\t$query .= implode(\",\\n\\t\", $tableDefinition);"},{"line":94,"text":"\t\t$query .= \"\\n)\";"},{"line":95,"text":"\t\t$query .= ' ' . $this->db->getSchemaManager()->getTableConfigSql($this->engine ?: null);"},{"line":96,"text":""},{"line":97,"text":"\t\tif ($this->comment)"},{"line":98,"text":"\t\t{"},{"line":99,"text":"\t\t\t$query .= ' COMMENT=' . $this->db->quote($this->comment);"},{"line":100,"text":"\t\t}"},{"line":101,"text":""},{"line":102,"text":"\t\tif ($this->autoIncrementIndex !== null)"},{"line":103,"text":"\t\t{"},{"line":104,"text":"\t\t\t$query .= ' AUTO_INCREMENT=' . $this->autoIncrementIndex;"},{"line":105,"text":"\t\t}"},{"line":106,"text":""},{"line":107,"text":"\t\t$queries[] = $query;"},{"line":108,"text":""},{"line":109,"text":"\t\treturn $queries;"},{"line":110,"text":"\t}"}]},"getCreateQuery":{"ok":false,"class":"XF\\Db\\Schema\\Create","method":"getCreateQuery","error":"ReflectionException"},"exists":{"ok":false,"class":"XF\\Db\\Schema\\Create","method":"exists","error":"ReflectionException"}},"source_scans":[{"file":"src/XF/Cli/Command/AddOnActionTrait.php","sha256":"265c7bd3e5dbeb5669b52e57fc9c67411261be00e493cc717aa6b5c991421287","hits":[{"line":15,"text":"use XF\\AddOn\\StepResult;"},{"line":118,"text":"/** @var StepResult $result */"},{"line":131,"text":"$params['step'] = $result->step;"},{"line":219,"text":"'xf:addon-sub-action',"}]},{"file":"src/XF/Cli/Command/AddOnInstall.php","sha256":"2407ad9ae20ca8ac1ca84b456ac2adc537f39c79534da5e258167a4d0df2a54f","hits":[{"line":20,"text":"->setName('xf:addon-install')"}]},{"file":"src/XF/Cli/Command/AddOnList.php","sha256":"3047ffa03d4fa488cb8a53c2f0c8c88edd8372e5804340f72b3fd761b7eff1ea","hits":[{"line":136,"text":"'last_pending_action' => $installed->last_pending_action,"},{"line":198,"text":"$installed->last_pending_action ?: '-',"}]},{"file":"src/XF/Cli/Command/AddOnSubAction.php","sha256":"4cbf315edc17bf5773c624da2d1af076f47dd588398462d657f709d832adbb46","hits":[{"line":18,"text":"->setName('xf:addon-sub-action')"},{"line":19,"text":"->setDescription('Runs a add-on sub-action in a separate process. Do not run directly!')"},{"line":46,"text":"$output->writeln(\"Invalid sub-action confirmation key. Run from parent command.\");"}]},{"file":"src/XF/Cli/Command/Import.php","sha256":"cbc8b5707e84a1b1293ca00f57dcc91bb0ded0d3810eb976d0b93327c1dd32f5","hits":[{"line":14,"text":"use XF\\Import\\StepState;"},{"line":39,"text":"'If set, the import will be automatically finalized when the data import step completes.'"},{"line":112,"text":"function ($isComplete, $step, StepState $stepState, $importCompletion) use ($progressIndicator, &$progressStarted)"},{"line":114,"text":"$stepTitle = $stepState->title;"},{"line":115,"text":"if (!$stepTitle)"},{"line":132,"text":"$stepNumberStrlen = strlen((string) $importCompletion['total']);"},{"line":133,"text":"$stepNameStrlen = 25; // just arbitrary for now, but could be based on the strlen of the longest step title"},{"line":135,"text":"$stepInfo = sprintf("},{"line":136,"text":"\"Step %{$stepNumberStrlen}d of %d: %-{$stepNameStrlen}s \","},{"line":139,"text":"$stepTitle"},{"line":142,"text":"if ($stepState->complete)"},{"line":145,"text":"$stepInfo"},{"line":146,"text":". $this->getIntervalString($stepState->startDate, $stepState->completeDate)"},{"line":147,"text":". ' [' . \\XF::language()->numberFormat($stepState->imported) . ']'"},{"line":154,"text":"$stepInfo"},{"line":155,"text":". $this->getIntervalString($stepState->startDate, time()) . ' '"},{"line":156,"text":". $stepState->getCompletionOutput()"}]},{"file":"src/XF/Cli/Command/ImportChildProcess.php","sha256":"4018331a7104801b8d7c73c6bf90374e198ed576897a7b4b01e5195c9d5133f9","hits":[{"line":24,"text":"'step',"},{"line":26,"text":"'The name of the step to run.'"},{"line":63,"text":"$step = $input->getArgument('step');"},{"line":67,"text":"if (!$runner->validateChildProcessRun($step, $startAfter, $end, $error))"},{"line":78,"text":"$runner->runChildProcess($step, $startAfter, $end, $messageReceiver);"}]},{"file":"src/XF/Cli/Command/ImportCommandTrait.php","sha256":"a4816d99b66aa795a1558e01dc42169c471af78028e103533326ced8365f970b","hits":[{"line":21,"text":"$totalsTable->setHeaders(['Step', 'Total', 'Time taken']);"}]},{"file":"src/XF/Cli/Command/ImportFinalize.php","sha256":"78b8ed78256f621c461fe11a6b206a3871819c9960660029feb8d76134ecfde8","hits":[{"line":64,"text":"$jobs = $manager->getImporter($session->importerId)->getFinalizeJobs($session->getStepsRun());"}]},{"file":"src/XF/Cli/Command/Upgrade.php","sha256":"9f58a531299befbb84458add55bb9e701fc18cd06f49d5c86c15fd5871af1a61","hits":[{"line":70,"text":". ($lastUpgradeVersion['last_step'] ? \" (step $lastUpgradeVersion[last_step])\" : '')"},{"line":75,"text":"$upgradeComplete = ($lastUpgradeVersion['version_id'] === \\XF::$versionId && !$lastUpgradeVersion['last_step']);"},{"line":104,"text":"$step = 1;"},{"line":106,"text":"if ($lastUpgradeVersion['last_step'])"},{"line":109,"text":"$step = $lastUpgradeVersion['last_step'] + 1;"},{"line":115,"text":"$step = 1;"},{"line":126,"text":"$upgrader->assertValidUpgradeSteps($upgrade);"},{"line":132,"text":"while (method_exists($upgrade, 'step' . $step))"},{"line":136,"text":"$this->outputStatus($output, \"Running upgrade to $versionName, step $step ($position)...\");"},{"line":140,"text":"$this->outputStatus($output, \"Running upgrade to $versionName, step $step...\");"},{"line":143,"text":"$result = $upgrade->{'step' . $step}($position, $data, $controller);"},{"line":146,"text":"$this->clearStatus($output, 'This step must be completed via the web interface.');"},{"line":151,"text":"$this->clearStatus($output, \"Running upgrade to $versionName, step $step... done.\");"},{"line":156,"text":"$upgrader->insertUpgradeLog($runVersionId, $step);"},{"line":158,"text":"$this->clearStatus($output, \"Running upgrade to $versionName, step $step... done.\");"},{"line":160,"text":"$step++;"},{"line":166,"text":"// stay on the same step"},{"line":172,"text":"$this->clearStatus($output, 'The upgrade step returned an unexpected result.');"},{"line":180,"text":"$step = 1;"},{"line":184,"text":"$output->writeln(['All upgrade steps run up to version ' . \\XF::$version . '.', '']);"}]},{"file":"src/XF/Cli/Command/AddOn/AbstractSetupStep.php","sha256":"86ac6e9eda2202a75f3566a6bf20b14b5cc5171a823e0a23de0e66d0e8c0a8b7","hits":[{"line":9,"text":"use XF\\AddOn\\StepResult;"},{"line":16,"text":"abstract class AbstractSetupStep extends AbstractCommand"},{"line":21,"text":"abstract protected function getStepType();"},{"line":27,"text":"$command = $this->getStepType();"},{"line":30,"text":"->setName('xf-addon:' . $command . '-step')"},{"line":31,"text":"->setDescription('Runs a specific step from the specified add-on Setup class.')"},{"line":60,"text":"$step = $input->getArgument('step');"},{"line":64,"text":"$stepType = $this->getStepType();"},{"line":65,"text":"if ($stepType == 'upgrade')"},{"line":70,"text":"$setup->prepareForAction($stepType);"},{"line":74,"text":"$result = $this->runStep($setup, $output, $stepType, $step, $version, $params);"},{"line":75,"text":"if (!($result instanceof StepResult))"},{"line":77,"text":"$this->clearStatus($output, \"Must return a StepResult object.\");"},{"line":104,"text":"protected function runStep(AbstractSetup $setup, OutputInterface $output, $stepType, $step, $version = null, array $params = [])"},{"line":106,"text":"$method = $stepType;"},{"line":112,"text":"if ($step)"},{"line":114,"text":"$method .= 'Step' . $step;"},{"line":119,"text":"if ($version && $step)"},{"line":121,"text":"$method .= $version . 'Step' . $step;"},{"line":129,"text":"return new StepResult(true);"},{"line":137,"text":"$result = new StepResult(true);"},{"line":142,"text":"$result = new StepResult(false, $result);"}]},{"file":"src/XF/Cli/Command/AddOn/Create.php","sha256":"4ff8f77caa12327158b9a6ba6ed2ffe85b959011279be5a70a8b3e77f75204f5","hits":[{"line":217,"text":"$question = new ConfirmationQuestion(\"Does your Setup need to support running multiple steps? (y/n) \");"},{"line":226,"text":"use XF\\AddOn\\StepRunnerInstallTrait;"},{"line":227,"text":"use XF\\AddOn\\StepRunnerUninstallTrait;"},{"line":228,"text":"use XF\\AddOn\\StepRunnerUpgradeTrait;"},{"line":232,"text":"use StepRunnerInstallTrait;"},{"line":233,"text":"use StepRunnerUpgradeTrait;"},{"line":234,"text":"use StepRunnerUninstallTrait;"},{"line":250,"text":"public function install(array \\$stepParams = [])"},{"line":255,"text":"public function upgrade(array \\$stepParams = [])"},{"line":260,"text":"public function uninstall(array \\$stepParams = [])"},{"line":283,"text":"$output->writeln(\"If you change your mind, create a file named Setup.php in \" . dirname($setupPath) . \" which should extend AbstractSetup and optionally use one of the StepRunnerX traits.\");"}]},{"file":"src/XF/Cli/Command/AddOn/InstallStep.php","sha256":"5536a7cdaa190b8ddff16e58733a546c3735ae8e55ab4c9d3cf1e1acce615ca2","hits":[{"line":7,"text":"class InstallStep extends AbstractSetupStep"},{"line":9,"text":"protected function getStepType()"},{"line":17,"text":"'step',"},{"line":19,"text":"'The step number to run.'"}]},{"file":"src/XF/Cli/Command/AddOn/UninstallStep.php","sha256":"d69b287acd3ea5c02bf23492e1bdef465fb75f22f00b45acdb4ffafe547260e5","hits":[{"line":7,"text":"class UninstallStep extends AbstractSetupStep"},{"line":9,"text":"protected function getStepType()"},{"line":17,"text":"'step',"},{"line":19,"text":"'The step number to run.'"}]},{"file":"src/XF/Cli/Command/AddOn/UpgradeStep.php","sha256":"51d6bcea38a819ab7a983340112de1b9778ed9efeb0a139f8d0b6c967b4e052f","hits":[{"line":7,"text":"class UpgradeStep extends AbstractSetupStep"},{"line":9,"text":"protected function getStepType()"},{"line":23,"text":"'step',"},{"line":25,"text":"'The step number to run.'"}]},{"file":"src/XF/Cli/Command/Rebuild/AbstractRebuildCommand.php","sha256":"9b019518b8fb2d2e3bf6d281acb57e181c4b48f2acbf654efdc81b87f294c7f4","hits":[{"line":56,"text":"'resume',"},{"line":73,"text":"if ($input->getOption('resume'))"},{"line":81,"text":"$output->writeln(\"There are no pending jobs of this type to resume.\");"}]},{"file":"src/XF/Cli/Command/EmbedMetadata/AbstractEmbedMetadataCommand.php","sha256":"d58bdc8eb04615e12b7838403db010fb05ff9238203467061fd7f0bb2d6274f9","hits":[{"line":74,"text":"'resume',"},{"line":77,"text":"'Resume an existing pending job instead of starting a new one. Without this flag, re-running the command discards any prior progress and restarts from the beginning.'"},{"line":92,"text":"if ($input->getOption('resume'))"},{"line":100,"text":"$output->writeln(\"There are no pending jobs of this type to resume.\");"}]},{"file":"src/XF/Cli/Command/Development/UpgradeStep.php","sha256":"6c91e119b41e5d2b83da72f7d37c02ff2f3d6149b7b7974e05ab3539f0e59fd5","hits":[{"line":18,"text":"class UpgradeStep extends AbstractCommand implements CustomAppCommandInterface"},{"line":30,"text":"->setName('xf-dev:upgrade-step')"},{"line":31,"text":"->setDescription('Runs a specific upgrade step from a specified upgrade class.')"},{"line":38,"text":"'step',"},{"line":40,"text":"'The step number to run'"},{"line":54,"text":"$step = $input->getArgument('step');"},{"line":60,"text":"$returnCode = $this->runStep($upgrade, $output, $controller, $step, $position, $data);"},{"line":73,"text":"throw new \\LogicException(\"Step did not return an expected result\");"},{"line":81,"text":"protected function runStep(AbstractUpgrade $upgrade, OutputInterface $output, Upgrade $controller, $step, $position = 0, $data = [])"},{"line":85,"text":"if (!method_exists($upgrade, 'step' . $step))"},{"line":87,"text":"$this->clearStatus($output, \"Upgrade to version $versionName does not have a step$step() method.\");"},{"line":93,"text":"$this->outputStatus($output, \"Running upgrade to $versionName, step $step ($position)...\");"},{"line":97,"text":"$this->outputStatus($output, \"Running upgrade to $versionName, step $step...\");"},{"line":100,"text":"$result = $upgrade->{'step' . $step}($position, $data, $controller);"},{"line":103,"text":"$this->clearStatus($output, \"This step must be completed via the web interface.\");"},{"line":108,"text":"$this->clearStatus($output, \"Running upgrade to $versionName, step $step... done.\");"},{"line":113,"text":"// stay on the same step"},{"line":118,"text":"$this->clearStatus($output, \"The upgrade step returned an unexpected result.\");"}]},{"file":"src/XF/AddOn/AbstractSetup.php","sha256":"6bdd3fe834e15b963a52c9357f54262f2d12f3c7c3686fc31333b549cddf2d88","hits":[{"line":21,"text":"* @param array $stepParams"},{"line":23,"text":"* @return null|StepResult"},{"line":25,"text":"abstract public function install(array $stepParams = []);"},{"line":28,"text":"* @param array $stepParams"},{"line":30,"text":"* @return null|StepResult"},{"line":32,"text":"abstract public function upgrade(array $stepParams = []);"},{"line":35,"text":"* @param array $stepParams"},{"line":37,"text":"* @return null|StepResult"},{"line":39,"text":"abstract public function uninstall(array $stepParams = []);"}]},{"file":"src/XF/AddOn/AddOn.php","sha256":"0e0346a046fff6bde9850cb53e9dc0d0b5379387029dc16925e562fa141ab422","hits":[{"line":346,"text":"$lastAction = $this->installedAddOn->getLastActionStep('install');"},{"line":349,"text":"// we haven't completed the install steps yet, don't consider as installed"},{"line":537,"text":"public function updatePendingAction($action, $step)"},{"line":541,"text":"$this->installedAddOn->fastUpdate('last_pending_action', \"$action:$step\");"},{"line":549,"text":"$this->installedAddOn->fastUpdate('last_pending_action', null);"},{"line":568,"text":"'last_pending_action' => 'install:0',"},{"line":653,"text":"$installed->last_pending_action = 'uninstall:0';"}]},{"file":"src/XF/AddOn/StepResult.php","sha256":"d486646b6b20370f7c03f473468ecec93e7cea3ef45cca8d72d6fe9b2701f9be","hits":[{"line":5,"text":"class StepResult"},{"line":9,"text":"public $step;"},{"line":12,"text":"public function __construct($complete, array $params = [], $step = null, $version = null)"},{"line":16,"text":"$this->step = $step;"}]},{"file":"src/XF/AddOn/StepRunnerInstallTrait.php","sha256":"1f441b8a3101b97009ae04e62c04e79062a89f1e01a08ae9e07c5e629c76d5f2","hits":[{"line":10,"text":"trait StepRunnerInstallTrait"},{"line":13,"text":"* @param array $stepParams"},{"line":15,"text":"* @return null|StepResult"},{"line":17,"text":"public function install(array $stepParams = [])"},{"line":19,"text":"$stepParams = array_replace(["},{"line":20,"text":"'step' => 0,"},{"line":21,"text":"], $stepParams);"},{"line":23,"text":"$step = $stepParams['step'];"},{"line":24,"text":"if (!$step)"},{"line":26,"text":"$step = $this->getInstallResumeStep();"},{"line":29,"text":"return $this->installStepRunner($step, $stepParams);"},{"line":32,"text":"private function getInstallResumeStep()"},{"line":37,"text":"$lastActionStep = $installedAddOn->getLastActionStep('install');"},{"line":38,"text":"if ($lastActionStep)"},{"line":40,"text":"return $lastActionStep + 1; // this is the last completed step, so resume with the next"},{"line":48,"text":"* @param integer $step"},{"line":49,"text":"* @param array $stepParams"},{"line":51,"text":"* @return null|StepResult"},{"line":53,"text":"private function installStepRunner($step, array $stepParams)"},{"line":55,"text":"$fnPrefix = 'installStep';"},{"line":56,"text":"$fn = $fnPrefix . $step;"},{"line":62,"text":"$result = $this->$fn($stepParams);"},{"line":65,"text":"$result = new StepResult(true);"},{"line":69,"text":"$result = new StepResult(false, $result);"},{"line":72,"text":"if (!($result instanceof StepResult))"},{"line":74,"text":"throw new \\LogicException(\"Must return a StepResult object\");"},{"line":77,"text":"$result->step = $step;"},{"line":81,"text":"$this->addOn->updatePendingAction('install', $result->step);"},{"line":83,"text":"$nextStep = $step + 1;"},{"line":84,"text":"$nextFn = $fnPrefix . $nextStep;"},{"line":90,"text":"$result = new StepResult(false, [], $nextStep);"}]},{"file":"src/XF/AddOn/StepRunnerUninstallTrait.php","sha256":"e58a9ab9c30e3cf3c41a0be392e8c5ac37f744578f7b91f76d663139649c49a9","hits":[{"line":10,"text":"trait StepRunnerUninstallTrait"},{"line":13,"text":"* @param array $stepParams"},{"line":15,"text":"* @return null|StepResult"},{"line":17,"text":"public function uninstall(array $stepParams = [])"},{"line":19,"text":"$stepParams = array_replace(["},{"line":20,"text":"'step' => 0,"},{"line":21,"text":"], $stepParams);"},{"line":23,"text":"$step = $stepParams['step'];"},{"line":24,"text":"if (!$step)"},{"line":26,"text":"$step = $this->getUninstallResumeStep();"},{"line":28,"text":"return $this->uninstallStepRunner($step, $stepParams);"},{"line":31,"text":"private function getUninstallResumeStep()"},{"line":36,"text":"$lastActionStep = $installedAddOn->getLastActionStep('uninstall');"},{"line":37,"text":"if ($lastActionStep)"},{"line":39,"text":"return $lastActionStep + 1; // this is the last completed step, so resume with the next"},{"line":47,"text":"* @param integer $step"},{"line":48,"text":"* @param array $stepParams"},{"line":50,"text":"* @return null|StepResult"},{"line":52,"text":"private function uninstallStepRunner($step, array $stepParams)"},{"line":54,"text":"$fnPrefix = 'uninstallStep';"},{"line":55,"text":"$fn = $fnPrefix . $step;"},{"line":61,"text":"$result = $this->$fn($stepParams);"},{"line":64,"text":"$result = new StepResult(true);"},{"line":68,"text":"$result = new StepResult(false, $result);"},{"line":71,"text":"if (!($result instanceof StepResult))"},{"line":73,"text":"throw new \\LogicException(\"Must return a StepResult object\");"},{"line":76,"text":"$result->step = $step;"},{"line":80,"text":"$this->addOn->updatePendingAction('uninstall', $result->step);"},{"line":82,"text":"$nextStep = $step + 1;"},{"line":83,"text":"$nextFn = $fnPrefix . $nextStep;"},{"line":89,"text":"$result = new StepResult(false, [], $nextStep);"}]},{"file":"src/XF/AddOn/StepRunnerUpgradeTrait.php","sha256":"b61698d9c20f094cc1b704ad48798148fe5843e2dc746592cb2db252b579d1b5","hits":[{"line":10,"text":"trait StepRunnerUpgradeTrait"},{"line":13,"text":"* @param array $stepParams"},{"line":15,"text":"* @return null|StepResult"},{"line":17,"text":"public function upgrade(array $stepParams = [])"},{"line":19,"text":"$stepParams = $this->getStepParams($stepParams);"},{"line":22,"text":"$stepsGrouped = [];"},{"line":27,"text":"if (preg_match('/^upgrade(\\d+)Step(\\d+)$/', $method->name, $match))"},{"line":30,"text":"$step = intval($match[2]);"},{"line":33,"text":"$stepsGrouped[$versionId][$step] = $step;"},{"line":42,"text":"if (!$stepParams['version_id'])"},{"line":44,"text":"$resume = $this->getUpgradeResumeStep();"},{"line":45,"text":"$stepParams['version_id'] = $resume[0];"},{"line":46,"text":"$stepParams['step'] = $resume[1];"},{"line":49,"text":"$runStep = $stepParams['step'];"},{"line":50,"text":"if (!$runStep)"},{"line":52,"text":"$runStep = 1;"},{"line":60,"text":"if ($versionId >= $stepParams['version_id'])"},{"line":62,"text":"$versionSteps = $stepsGrouped[$versionId];"},{"line":63,"text":"if (isset($versionSteps[$runStep]))"},{"line":65,"text":"if ($versionId != $stepParams['version_id'] || $runStep != $stepParams['step'])"},{"line":67,"text":"// sanity check - don't pass params if we're changing versions or steps"},{"line":68,"text":"$stepParams = [];"},{"line":73,"text":"return $this->upgradeStepRunner($versionId, $runStep, $stepParams, $nextVersionId);"},{"line":76,"text":"// if we hit here, then the step couldn't be found, so move onto the next upgrade"},{"line":77,"text":"$runStep = 1;"},{"line":78,"text":"$stepParams = $this->getStepParams();"},{"line":86,"text":"protected function getStepParams(array $stepParams = [])"},{"line":90,"text":"'step' => 0,"},{"line":91,"text":"], $stepParams);"},{"line":94,"text":"private function getUpgradeResumeStep()"},{"line":97,"text":"$lastActionStep = $installedAddOn->getLastActionStep('upgrade');"},{"line":98,"text":"if ($lastActionStep)"},{"line":100,"text":"$lastActionStep[1]++; // we completed this step, so need to resume with the next"},{"line":101,"text":"return $lastActionStep;"},{"line":109,"text":"* @param integer $runStep"},{"line":110,"text":"* @param array $stepParams"},{"line":113,"text":"* @return null|StepResult"},{"line":115,"text":"private function upgradeStepRunner($runVersion, $runStep, array $stepParams, $nextVersionId)"},{"line":117,"text":"$fnPattern = 'upgrade%dStep%d';"},{"line":118,"text":"$fn = sprintf($fnPattern, $runVersion, $runStep);"},{"line":121,"text":"throw new \\LogicException(\"Step $fn doesn't exist. Should have been checked earlier.\");"},{"line":124,"text":"$result = $this->$fn($stepParams);"},{"line":127,"text":"$result = new StepResult(true);"},{"line":131,"text":"$result = new StepResult(false, $result);"},{"line":134,"text":"if (!($result instanceof StepResult))"},{"line":136,"text":"throw new \\LogicException(\"Must return a StepResult object\");"},{"line":139,"text":"$result->step = $runStep;"},{"line":144,"text":"$this->addOn->updatePendingAction('upgrade', $result->version . ':' . $result->step);"},{"line":146,"text":"$nextStep = $runStep + 1;"},{"line":147,"text":"$nextStepFn = sprintf($fnPattern, $runVersion, $nextStep);"},{"line":148,"text":"if (method_exists($this, $nextStepFn))"},{"line":150,"text":"$result = new StepResult(false, [], $nextStep, $runVersion);"},{"line":166,"text":"$result = new StepResult(false, [], 1, $nextVersionId);"}]},{"file":"src/XF/AddOn/DataType/AbstractDataType.php","sha256":"a4f6ec14e4009be0029548b07272dc77c6ad96f4cca4e067a7d3ea0004126815","hits":[{"line":165,"text":"protected function resume($maxRunTime, $startTime)"}]}]},"assessment":{"all_six_tables_present":true,"all_six_tables_empty":true,"duplicate_create_appears_safe":true,"native_resume_signal":true},"policy":{"delete_performed":false,"mutation_performed":false,"goal":"select a no-delete native or bounded bridge install path"}} +GRAM513R3R3_DECISION=PASS_NATIVE_RESUME_SCHEMA_RCA +GRAM513R3R3_NEXT_GATE=READY_FOR_DIRECT_NATIVE_RETRY_CANARY_513R3R4 +HOMELAB_RESULT_CONTRACT={"version":1,"command_id":"SUPPORT-260918-GRAM-XF-CODEVIPE-NATIVE-RESUME-SCHEMA-RCA-513R3R3","status":"OK","changes_made":false,"rollback_started":false,"rollback_restored":null} + +OUTPUT_END +CHAT_OUTPUT_END diff --git a/runtime/latest.json b/runtime/latest.json index 57c3f9dd..ee585491 100644 --- a/runtime/latest.json +++ b/runtime/latest.json @@ -1,19 +1,19 @@ { "schema_version": 1, "channel": "homelab-runtime", - "command_id": "SUPPORT-260918-GRAM-XF-CODEVIPE-PARTIAL-STATE-INSTALLABILITY-RCA-513R3R2", + "command_id": "SUPPORT-260918-GRAM-XF-CODEVIPE-NATIVE-RESUME-SCHEMA-RCA-513R3R3", "status": "OK", "rc": 0, "host": "pve01", "mode": "read-only", - "component": "gram-support-codevipe-partial-state-installability-rca", - "started_at_utc": "2026-09-18T01:28:11Z", - "finished_at_utc": "2026-09-18T01:28:13Z", + "component": "gram-support-codevipe-native-resume-schema-rca", + "started_at_utc": "2026-09-18T01:33:03Z", + "finished_at_utc": "2026-09-18T01:33:05Z", "reference_register_checked": true, "reference_sha256": "5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66", "error_register_checked": true, "error_register_sha256": "3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0", - "command_sha256": "2007a08bdd3a7e3c5541e130c8f14d46a334da28d493dc7aaa74707f6ed4d2b7", + "command_sha256": "d024725d107ae38e09893a322f7a365399e215a929d3c723a3099129609390bf", "duplicate_failed_command_blocked": false, "block_reason": null, "execution_started": true, @@ -30,9 +30,9 @@ "secrets_included": false, "private_addresses_included": false, "raw_evidence_retained_locally": true, - "raw_evidence_sha256": "f8164218838f14dc4258bebe0143a275376e0dd5cd30c7c34d38151d3b94a72d", - "sanitized_output_sha256": "f8164218838f14dc4258bebe0143a275376e0dd5cd30c7c34d38151d3b94a72d", + "raw_evidence_sha256": "3356fd66c51344f1c1c25279dd2f3ad70b12040178c3a7513b0aa812b569ae94", + "sanitized_output_sha256": "3356fd66c51344f1c1c25279dd2f3ad70b12040178c3a7513b0aa812b569ae94", "output_truncated_in_json": false, "full_sanitized_output_url": "https://git.gram1.ru/.well-known/homelab-runtime/latest.txt", - "output": "GRAM513R3R2_WRAPPER_BEGIN=true\nERROR_REGISTER_CHECK=OK\nREFERENCE_CHECK=OK\nAUTHORITY_CHECK_SCOPE=READABILITY_ONLY_INCIDENTS_NOT_CLOSED\nGRAM513R3R2_SAFE_REPORT={\"artifact\":{\"sha256\":\"2e31f89d3626a83c1211910aa6fd279cc04689b75ba822899952865085cf551e\",\"version_id\":1000120,\"version_string\":\"1.0.0 Alpha 3 Unified Fix 10\",\"setup_sha256\":\"4977f90ec0444e2e3a1e4ee9b79a4e88098c5a3ae37b30d63e77cff2e1fcb971\",\"template_modifications_sha256\":\"04f338a8107a80bd3c17b6f6888faea596a5057140556ce6f4f1673d2034628b\"},\"setup_hits\":[{\"line\":15,\"text\":\"public function installStep1(): void\",\"context\":\" use StepRunnerUninstallTrait;\\\\n\\\\n public function installStep1(): void\\\\n {\\\\n $sm = $this->schemaManager();\\\\n $sm->createTable('xf_gram_support_ticket', function($table) {\"},{\"line\":17,\"text\":\"$sm = $this->schemaManager();\",\"context\":\" public function installStep1(): void\\\\n {\\\\n $sm = $this->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);\"},{\"line\":18,\"text\":\"$sm->createTable('xf_gram_support_ticket', function($table) {\",\"context\":\" {\\\\n $sm = $this->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);\"},{\"line\":44,\"text\":\"$sm->createTable('xf_gram_support_message', function($table) {\",\"context\":\" $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);\"},{\"line\":56,\"text\":\"$sm->createTable('xf_gram_support_event', function($table) {\",\"context\":\" $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);\"},{\"line\":68,\"text\":\"$sm->createTable('xf_gram_support_attachment_meta', function($table) {\",\"context\":\" });\\\\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);\"},{\"line\":78,\"text\":\"$sm->createTable('xf_gram_support_delivery', function($table) {\",\"context\":\" $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);\"},{\"line\":94,\"text\":\"$sm->createTable('xf_gram_support_rate_limit', function($table) {\",\"context\":\" $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);\"},{\"line\":104,\"text\":\"public function uninstallStep1(): void\",\"context\":\" }\\\\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) {\"},{\"line\":106,\"text\":\"$sm = $this->schemaManager();\",\"context\":\" 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 }\"},{\"line\":108,\"text\":\"$sm->dropTable($name);\",\"context\":\" $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}\"}],\"templates\":{\"gram_support.less\":{\"version_id\":\"1000100\",\"version_string\":\"1.0.0 Alpha 3 Unified Fix 8\",\"content\":\".gramSupport-launcher\\n{\\n\\tposition: fixed;\\n\\tright: 18px;\\n\\tbottom: 18px;\\n\\tz-index: 500;\\n\\tborder-radius: 999px;\\n\\tbox-shadow: 0 6px 24px rgba(0, 0, 0, .22);\\n}\\n\\n.gramSupport-messageMeta\\n{\\n\\tfont-size: 12px;\\n\\topacity: .7;\\n\\tmargin-bottom: 6px;\\n}\\n\\n.gramSupport-message--internal\\n{\\n\\tborder-left: 4px solid currentColor;\\n\\topacity: .9;\\n}\\n\\n@media (max-width: 650px)\\n{\\n\\t.gramSupport-launcher\\n\\t{\\n\\t\\tright: 12px;\\n\\t\\tbottom: 12px;\\n\\t\\tmax-width: calc(100vw - 24px);\\n\\t}\\n}\\n\\n.gramSupport-messageBody\\n{\\n\\twhite-space: pre-wrap;\\n\\toverflow-wrap: anywhere;\\n}\\n\\n/* gram-support-footer-center-v1 */\\n.gramSupport-launcher\\n{\\n position: static;\\n inset: auto;\\n z-index: auto;\\n flex: 1 1 auto;\\n display: flex;\\n justify-content: center;\\n align-items: center;\\n width: auto;\\n max-width: none;\\n padding: 5px 18px;\\n}\\n\\n.gramSupport-launcher .button.button--primary\\n{\\n position: relative;\\n overflow: hidden;\\n display: inline-flex;\\n align-items: center;\\n justify-content: center;\\n min-width: 220px;\\n min-height: 52px;\\n padding: 11px 24px;\\n border: 1px solid rgba(255, 213, 122, .78);\\n border-radius: 14px;\\n color: #fff1c4;\\n background-image:\\n linear-gradient(110deg, transparent 0%, transparent 43%, rgba(255, 255, 255, .42) 50%, transparent 57%, transparent 100%),\\n linear-gradient(135deg, #533100 0%, #9a6208 24%, #d8a63a 48%, #a76d0b 70%, #4a2b00 100%);\\n background-size: 260% 100%, 100% 100%;\\n background-position: 180% 0, 0 0;\\n box-shadow: inset 0 0 0 1px rgba(255, 246, 210, .12), 0 0 22px rgba(220, 166, 49, .38), 0 9px 26px rgba(0, 0, 0, .30);\\n text-shadow: 0 1px 1px rgba(0, 0, 0, .45);\\n animation: gramSupportFooterShimmer 4.8s ease-in-out infinite;\\n transition: transform .18s ease, box-shadow .18s ease, filter .18s ease;\\n}\\n\\n.gramSupport-launcher .button.button--primary:hover,\\n.gramSupport-launcher .button.button--primary:focus-visible\\n{\\n filter: brightness(1.10) saturate(1.08);\\n transform: translateY(-1px);\\n box-shadow: inset 0 0 0 1px rgba(255, 249, 224, .20), 0 0 28px rgba(235, 184, 67, .50), 0 11px 30px rgba(0, 0, 0, .34);\\n}\\n\\n.gramSupport-launcher .button-text\\n{\\n position: relative;\\n display: inline-flex;\\n align-items: center;\\n justify-content: center;\\n gap: 10px;\\n font-size: 17px;\\n font-weight: 600;\\n letter-spacing: .01em;\\n}\\n\\n.gramSupport-launcher .button-text::before\\n{\\n content: \\\"\\\";\\n flex: 0 0 auto;\\n width: 20px;\\n height: 16px;\\n box-sizing: border-box;\\n border: 2px solid currentColor;\\n border-bottom: 0;\\n border-radius: 12px 12px 0 0;\\n}\\n\\n.gramSupport-launcher .button-text::after\\n{\\n content: \\\"\\\";\\n position: absolute;\\n left: 0;\\n top: 50%;\\n width: 4px;\\n height: 8px;\\n border-radius: 3px;\\n background: currentColor;\\n box-shadow: 16px 0 0 currentColor;\\n transform: translateY(-5%);\\n}\\n\\n@keyframes gramSupportFooterShimmer\\n{\\n 0%, 56% { background-position: 180% 0, 0 0; }\\n 82%, 100% { background-position: -80% 0, 0 0; }\\n}\\n\\n@media (max-width: 650px)\\n{\\n .p-footer-row\\n {\\n flex-wrap: wrap;\\n }\\n\\n .gramSupport-launcher\\n {\\n order: 3;\\n flex: 0 0 100%;\\n width: 100%;\\n max-width: none;\\n padding: 10px 0 2px;\\n }\\n\\n .gramSupport-launcher .button.button--primary\\n {\\n width: calc(100% - 32px);\\n max-width: 320px;\\n }\\n}\\n\\n@media (prefers-reduced-motion: reduce)\\n{\\n .gramSupport-launcher .button.button--primary\\n {\\n animation: none;\\n transition: none;\\n }\\n}\\n\\n/* gram-support-footer-align-v2 */\\n@media (min-width: 901px)\\n{\\n .p-footer-row\\n {\\n position: relative;\\n min-height: 64px;\\n }\\n\\n .gramSupport-launcher\\n {\\n position: absolute;\\n left: 50%;\\n top: 50%;\\n right: auto;\\n bottom: auto;\\n inset: auto;\\n transform: translate(-50%, -50%);\\n flex: 0 0 auto;\\n width: auto;\\n max-width: none;\\n padding: 0;\\n margin: 0;\\n z-index: 2;\\n }\\n}\\n\\n@media (max-width: 900px)\\n{\\n .p-footer-row\\n {\\n flex-wrap: wrap;\\n }\\n\\n .gramSupport-launcher\\n {\\n position: static;\\n inset: auto;\\n transform: none;\\n order: 3;\\n flex: 0 0 100%;\\n width: 100%;\\n max-width: none;\\n padding: 10px 0 2px;\\n margin: 0;\\n z-index: auto;\\n }\\n\\n .gramSupport-launcher .button.button--primary\\n {\\n width: calc(100% - 32px);\\n max-width: 320px;\\n }\\n}\\n\\n/* gram-support-footer-align-v3-mobile-center */\\n@media (max-width: 900px)\\n{\\n .gramSupport-launcher\\n {\\n display: flex;\\n justify-content: center;\\n align-items: center;\\n text-align: center;\\n }\\n\\n .gramSupport-launcher .button.button--primary\\n {\\n margin-left: auto;\\n margin-right: auto;\\n }\\n}\\n\\n/* gram-support-footer-align-v4-desktop-inset */\\n@media (min-width: 901px)\\n{\\n .gramSupport-launcher\\n {\\n inset: 50% auto auto 50%;\\n transform: translate(-50%, -50%);\\n }\\n}\\n\\n/* gram-support-footer-align-v5-gap-grid */\\n@media (min-width: 901px)\\n{\\n .p-footer-row\\n {\\n display: grid;\\n grid-template-columns: max-content minmax(0, 1fr) max-content;\\n align-items: center;\\n column-gap: 16px;\\n }\\n\\n .p-footer-row-main\\n {\\n grid-column: 1;\\n min-width: 0;\\n }\\n\\n .p-footer-row > .gramSupport-launcher\\n {\\n grid-column: 2;\\n grid-row: 1;\\n position: static;\\n inset: auto;\\n transform: none;\\n width: auto;\\n margin: 0;\\n justify-self: center;\\n align-self: center;\\n }\\n\\n .p-footer-row-opposite\\n {\\n grid-column: 3;\\n min-width: 0;\\n justify-self: end;\\n }\\n}\\n\\n/* gram-support-footer-align-v6-gap-grid-force */\\n@keyframes gramSupportFooterShimmerV6\\n{\\n 0% { background-position: 0% 50%; }\\n 100% { background-position: 200% 50%; }\\n}\\n\\nhtml body .p-footer .p-footer-row\\n{\\n position: relative !important;\\n}\\n\\nhtml body .p-footer .p-footer-row > .gramSupport-launcher.button\\n{\\n display: inline-flex !important;\\n align-items: center !important;\\n justify-content: center !important;\\n gap: .45em !important;\\n box-sizing: border-box !important;\\n min-height: 38px !important;\\n max-width: 100% !important;\\n padding: 8px 16px !important;\\n border: 1px solid rgba(255, 225, 128, .88) !important;\\n border-radius: 999px !important;\\n color: #241700 !important;\\n background: linear-gradient(120deg, #7c4b00 0%, #c88a16 18%, #f0c85a 36%, #fff1a8 50%, #d9a52f 66%, #8a5404 84%, #c88a16 100%) !important;\\n background-size: 220% 100% !important;\\n box-shadow: 0 0 14px rgba(235, 176, 44, .42), 0 0 28px rgba(235, 176, 44, .16), inset 0 1px 0 rgba(255, 255, 255, .45) !important;\\n font-weight: 700 !important;\\n line-height: 1.2 !important;\\n text-decoration: none !important;\\n white-space: nowrap !important;\\n animation: gramSupportFooterShimmerV6 3.2s linear infinite !important;\\n}\\n\\nhtml body .p-footer .p-footer-row > .gramSupport-launcher.button::before\\n{\\n content: \\\" \\\" !important;\\n display: inline-block !important;\\n flex: 0 0 16px !important;\\n width: 16px !important;\\n height: 14px !important;\\n box-sizing: border-box !important;\\n margin-right: .10em !important;\\n color: #2b1a00 !important;\\n border: 2px solid currentColor !important;\\n border-bottom: 0 !important;\\n border-radius: 9px 9px 2px 2px !important;\\n background:\\n linear-gradient(currentColor, currentColor) left bottom / 3px 6px no-repeat,\\n linear-gradient(currentColor, currentColor) right bottom / 3px 6px no-repeat !important;\\n}\\n\\n@media (min-width: 901px)\\n{\\n html body .p-footer .p-footer-row\\n {\\n display: grid !important;\\n grid-template-columns: max-content minmax(0, 1fr) max-content !important;\\n align-items: center !important;\\n column-gap: 16px !important;\\n }\\n\\n html body .p-footer .p-footer-row-main\\n {\\n grid-column: 1 !important;\\n grid-row: 1 !important;\\n float: none !important;\\n min-width: 0 !important;\\n margin-left: 0 !important;\\n margin-right: 0 !important;\\n }\\n\\n html body .p-footer .p-footer-row-opposite\\n {\\n grid-column: 3 !important;\\n grid-row: 1 !important;\\n float: none !important;\\n min-width: 0 !important;\\n margin-left: 0 !important;\\n margin-right: 0 !important;\\n justify-self: end !important;\\n }\\n\\n html body .p-footer .p-footer-row > .gramSupport-launcher.button\\n {\\n grid-column: 2 !important;\\n grid-row: 1 !important;\\n position: static !important;\\n inset: auto !important;\\n top: auto !important;\\n right: auto !important;\\n bottom: auto !important;\\n left: auto !important;\\n transform: none !important;\\n width: max-content !important;\\n margin: 0 !important;\\n float: none !important;\\n justify-self: center !important;\\n align-self: center !important;\\n }\\n}\\n\\n@media (max-width: 900px)\\n{\\n html body .p-footer .p-footer-row\\n {\\n display: grid !important;\\n grid-template-columns: minmax(0, 1fr) !important;\\n align-items: center !important;\\n row-gap: 8px !important;\\n }\\n\\n html body .p-footer .p-footer-row-main\\n {\\n grid-column: 1 !important;\\n grid-row: 1 !important;\\n float: none !important;\\n min-width: 0 !important;\\n margin-left: 0 !important;\\n margin-right: 0 !important;\\n justify-self: stretch !important;\\n }\\n\\n html body .p-footer .p-footer-row-opposite\\n {\\n grid-column: 1 !important;\\n grid-row: 2 !important;\\n float: none !important;\\n min-width: 0 !important;\\n margin-left: 0 !important;\\n margin-right: 0 !important;\\n justify-self: stretch !important;\\n }\\n\\n html body .p-footer .p-footer-row > .gramSupport-launcher.button\\n {\\n grid-column: 1 !important;\\n grid-row: 3 !important;\\n position: static !important;\\n inset: auto !important;\\n top: auto !important;\\n right: auto !important;\\n bottom: auto !important;\\n left: auto !important;\\n transform: none !important;\\n width: max-content !important;\\n margin: 4px 0 0 !important;\\n float: none !important;\\n justify-self: center !important;\\n align-self: center !important;\\n }\\n}\\n\\n\",\"sha256\":\"4482bdc4eadbbaa7cd515303a1a76500eb4be2dfeb1a4d0ebd41ea99b2465e17\"},\"gram_support_launcher\":{\"version_id\":\"1000050\",\"version_string\":\"1.0.0 Alpha 3 Unified Fix 3\",\"content\":\"\\n\\n\\n\\n\\t\\n\\t\\t{{ phrase('gram_support_open_support') }}\\n\\t\\n\\n\",\"sha256\":\"eb8510732480507f86c2401a5d49c465820c225c9a3519530f751f6f501eaf5d\"}},\"codevipe\":{\"ok\":true,\"addon\":null,\"counts\":{\"xf_content_type_field\":0,\"xf_code_event_listener\":0,\"xf_option\":0,\"xf_option_group\":0,\"xf_permission\":0,\"xf_permission_interface_group\":0,\"xf_phrase\":0,\"xf_route\":0,\"xf_template\":0,\"xf_template_modification\":0},\"support_tables\":[\"xf_gram_support_attachment_meta\",\"xf_gram_support_delivery\",\"xf_gram_support_event\",\"xf_gram_support_message\",\"xf_gram_support_rate_limit\",\"xf_gram_support_ticket\"],\"support_table_rows\":{\"xf_gram_support_attachment_meta\":0,\"xf_gram_support_delivery\":0,\"xf_gram_support_event\":0,\"xf_gram_support_message\":0,\"xf_gram_support_rate_limit\":0,\"xf_gram_support_ticket\":0},\"routes\":[],\"jobs\":[{\"job_id\":4,\"execute_class\":\"XF\\\\Job\\\\Cron\",\"manual_execute\":0},{\"job_id\":50,\"execute_class\":\"XF\\\\Job\\\\UpgradeCheck\",\"manual_execute\":0}],\"error_max\":0,\"recent_errors\":[],\"schema_manager_createTable\":{\"ok\":true,\"class\":\"XF\\\\Db\\\\SchemaManager\",\"parameters\":[{\"name\":\"tableName\",\"optional\":false},{\"name\":\"toApply\",\"optional\":false}],\"file_basename\":\"SchemaManager.php\",\"start\":187,\"end\":200,\"source_sha256\":\"be6c143b9b8321148d841530fe0e5f8388b5fa178a96a8a1fe759e8208eb71a4\",\"key_lines\":[{\"line\":187,\"text\":\"public function createTable($tableName, \\\\Closure $toApply)\"},{\"line\":189,\"text\":\"$create = $this->newTable($tableName);\"},{\"line\":193,\"text\":\"$toApply($create);\"},{\"line\":194,\"text\":\"$create->apply();\"},{\"line\":198,\"text\":\"$this->handleException($e, $tableName, $create);\"}]},\"board_active\":\"1\",\"board_url\":\"https://codevipe.ru\"},\"assessment\":{\"expected_partial_state\":true,\"support_tables_all_empty\":true,\"schema_createTable_truthy_optional_default\":false,\"schema_createTable_exists_signal\":false,\"setup_createTable_hits\":6,\"setup_dropTable_hits\":1,\"retry_without_delete_candidate\":false},\"requested_footer_patch\":{\"goal\":\"center button in remaining gap between left footer block and right footer links; vertical center aligned with footer text\",\"css_override\":\".p-footer-row {\\n align-items: center;\\n}\\n.gramSupport-launcher {\\n position: static;\\n flex: 1 1 auto;\\n min-width: 0;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n align-self: center;\\n margin: 0 16px;\\n}\\n.gramSupport-launcher .button {\\n margin: 0;\\n}\",\"strategy\":\"launcher already inserted immediately before p-footer-row-opposite; make launcher flex-grow and center contents\"}}\nGRAM513R3R2_DECISION=PASS_PARTIAL_STATE_INSTALLABILITY_RCA\nGRAM513R3R2_NEXT_GATE=HOLD_REQUIRES_INSTALL_PATH_DECISION_NO_DELETE\nHOMELAB_RESULT_CONTRACT={\"version\":1,\"command_id\":\"SUPPORT-260918-GRAM-XF-CODEVIPE-PARTIAL-STATE-INSTALLABILITY-RCA-513R3R2\",\"status\":\"OK\",\"changes_made\":false,\"rollback_started\":false,\"rollback_restored\":null}\n" + "output": "GRAM513R3R3_WRAPPER_BEGIN=true\nERROR_REGISTER_CHECK=OK\nREFERENCE_CHECK=OK\nAUTHORITY_CHECK_SCOPE=READABILITY_ONLY_INCIDENTS_NOT_CLOSED\nGRAM513R3R3_SAFE_REPORT={\"artifact\":{\"sha256\":\"2e31f89d3626a83c1211910aa6fd279cc04689b75ba822899952865085cf551e\",\"version_id\":1000120,\"version_string\":\"1.0.0 Alpha 3 Unified Fix 10\",\"setup_tables\":[\"xf_gram_support_ticket\",\"xf_gram_support_message\",\"xf_gram_support_event\",\"xf_gram_support_attachment_meta\",\"xf_gram_support_delivery\",\"xf_gram_support_rate_limit\"],\"setup_sha256\":\"4977f90ec0444e2e3a1e4ee9b79a4e88098c5a3ae37b30d63e77cff2e1fcb971\"},\"codevipe\":{\"ok\":true,\"tables\":{\"xf_gram_support_ticket\":{\"exists\":true,\"rows\":0,\"ddl_sha256\":\"3558077fc70b4453960d1d782998ad498b2d3b12ba587488e8b23785979f7ba8\",\"ddl\":\"CREATE TABLE `xf_gram_support_ticket` (\\n `ticket_id` int(10) unsigned NOT NULL AUTO_INCREMENT,\\n `public_ref` varchar(64) NOT NULL,\\n `site_id` varchar(32) NOT NULL,\\n `user_id` int(10) unsigned NOT NULL DEFAULT 0,\\n `guest_email` varchar(255) NOT NULL DEFAULT '',\\n `guest_access_token_hash` char(64) NOT NULL DEFAULT '',\\n `guest_access_expires` int(10) unsigned NOT NULL DEFAULT 0,\\n `node_id` int(10) unsigned NOT NULL DEFAULT 0,\\n `thread_id` int(10) unsigned NOT NULL DEFAULT 0,\\n `post_id` int(10) unsigned NOT NULL DEFAULT 0,\\n `category` varchar(64) NOT NULL DEFAULT '',\\n `subject` varchar(255) NOT NULL DEFAULT '',\\n `status` varchar(32) NOT NULL DEFAULT 'NEW',\\n `assigned_user_id` int(10) unsigned NOT NULL DEFAULT 0,\\n `created_date` int(10) unsigned NOT NULL DEFAULT 0,\\n `updated_date` int(10) unsigned NOT NULL DEFAULT 0,\\n `resolved_date` int(10) unsigned NOT NULL DEFAULT 0,\\n `context_json` mediumtext NOT NULL,\\n `last_message_id` int(10) unsigned NOT NULL DEFAULT 0,\\n PRIMARY KEY (`ticket_id`),\\n UNIQUE KEY `public_ref` (`public_ref`),\\n KEY `guest_token_hash` (`guest_access_token_hash`),\\n KEY `site_user_updated` (`site_id`,`user_id`,`updated_date`),\\n KEY `site_status_updated` (`site_id`,`status`,`updated_date`)\\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci\"},\"xf_gram_support_message\":{\"exists\":true,\"rows\":0,\"ddl_sha256\":\"a00e534c642179db3018c74060d1aa6cef4dc445dcb801eb847c04d770f8f884\",\"ddl\":\"CREATE TABLE `xf_gram_support_message` (\\n `message_id` int(10) unsigned NOT NULL AUTO_INCREMENT,\\n `ticket_id` int(10) unsigned NOT NULL,\\n `user_id` int(10) unsigned NOT NULL DEFAULT 0,\\n `is_staff` tinyint(3) unsigned NOT NULL DEFAULT 0,\\n `is_internal` tinyint(3) unsigned NOT NULL DEFAULT 0,\\n `message` mediumtext NOT NULL,\\n `message_date` int(10) unsigned NOT NULL DEFAULT 0,\\n PRIMARY KEY (`message_id`),\\n KEY `ticket_date` (`ticket_id`,`message_date`),\\n KEY `ticket_public_date` (`ticket_id`,`is_internal`,`message_date`)\\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci\"},\"xf_gram_support_event\":{\"exists\":true,\"rows\":0,\"ddl_sha256\":\"81b6328dbbcf3f6405891897ba185e29890c675f21d7a2f9caf827c0eddb42da\",\"ddl\":\"CREATE TABLE `xf_gram_support_event` (\\n `event_id` int(10) unsigned NOT NULL AUTO_INCREMENT,\\n `ticket_id` int(10) unsigned NOT NULL,\\n `site_id` varchar(32) NOT NULL,\\n `actor_user_id` int(10) unsigned NOT NULL DEFAULT 0,\\n `event_type` varchar(64) NOT NULL,\\n `event_date` int(10) unsigned NOT NULL DEFAULT 0,\\n `safe_payload_json` mediumtext NOT NULL,\\n PRIMARY KEY (`event_id`),\\n KEY `ticket_date` (`ticket_id`,`event_date`)\\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci\"},\"xf_gram_support_attachment_meta\":{\"exists\":true,\"rows\":0,\"ddl_sha256\":\"3c3d2ce4c5dae793687243dca37f60cd781895818b546a68e227aef9bfc9b6b2\",\"ddl\":\"CREATE TABLE `xf_gram_support_attachment_meta` (\\n `attachment_id` int(10) unsigned NOT NULL,\\n `ticket_id` int(10) unsigned NOT NULL,\\n `message_id` int(10) unsigned NOT NULL DEFAULT 0,\\n `is_internal` tinyint(3) unsigned NOT NULL DEFAULT 0,\\n `created_date` int(10) unsigned NOT NULL DEFAULT 0,\\n PRIMARY KEY (`attachment_id`),\\n KEY `ticket_internal` (`ticket_id`,`is_internal`),\\n KEY `message_id` (`message_id`)\\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci\"},\"xf_gram_support_delivery\":{\"exists\":true,\"rows\":0,\"ddl_sha256\":\"91f068994bdbe4b168ab1c82fa669180f13825e6d1a7f5b9e956ccc872d0410d\",\"ddl\":\"CREATE TABLE `xf_gram_support_delivery` (\\n `delivery_key` char(64) NOT NULL,\\n `event_id` int(10) unsigned NOT NULL,\\n `consumer` varchar(32) NOT NULL,\\n `recipient_key` varchar(96) NOT NULL,\\n `state` varchar(16) NOT NULL DEFAULT 'pending',\\n `lease_expires` int(10) unsigned NOT NULL DEFAULT 0,\\n `attempt_count` int(10) unsigned NOT NULL DEFAULT 0,\\n `last_failure_class` varchar(191) NOT NULL DEFAULT '',\\n `created_date` int(10) unsigned NOT NULL DEFAULT 0,\\n `updated_date` int(10) unsigned NOT NULL DEFAULT 0,\\n `sent_date` int(10) unsigned NOT NULL DEFAULT 0,\\n PRIMARY KEY (`delivery_key`),\\n KEY `event_consumer` (`event_id`,`consumer`),\\n KEY `state_lease` (`state`,`lease_expires`)\\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci\"},\"xf_gram_support_rate_limit\":{\"exists\":true,\"rows\":0,\"ddl_sha256\":\"f2271e20d520a8ba413b2094a4f8f6640395065c7d9c2e4f5b0a74b790d3dd8e\",\"ddl\":\"CREATE TABLE `xf_gram_support_rate_limit` (\\n `rate_key` char(64) NOT NULL,\\n `window_start` int(10) unsigned NOT NULL,\\n `hit_count` int(10) unsigned NOT NULL DEFAULT 0,\\n `updated_date` int(10) unsigned NOT NULL DEFAULT 0,\\n PRIMARY KEY (`rate_key`),\\n KEY `updated_date` (`updated_date`)\\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci\"}},\"addon\":null,\"schema_manager_class\":\"XF\\\\Db\\\\SchemaManager\",\"schema_methods\":{\"createTable\":{\"ok\":true,\"class\":\"XF\\\\Db\\\\SchemaManager\",\"method\":\"createTable\",\"file\":\"SchemaManager.php\",\"start\":187,\"end\":200,\"sha256\":\"be6c143b9b8321148d841530fe0e5f8388b5fa178a96a8a1fe759e8208eb71a4\",\"source\":\"\\tpublic function createTable($tableName, \\\\Closure $toApply)\\n\\t{\\n\\t\\t$create = $this->newTable($tableName);\\n\\n\\t\\ttry\\n\\t\\t{\\n\\t\\t\\t$toApply($create);\\n\\t\\t\\t$create->apply();\\n\\t\\t}\\n\\t\\tcatch (\\\\Exception $e)\\n\\t\\t{\\n\\t\\t\\t$this->handleException($e, $tableName, $create);\\n\\t\\t}\\n\\t}\\n\",\"lines\":[{\"line\":187,\"text\":\"\\tpublic function createTable($tableName, \\\\Closure $toApply)\"},{\"line\":188,\"text\":\"\\t{\"},{\"line\":189,\"text\":\"\\t\\t$create = $this->newTable($tableName);\"},{\"line\":190,\"text\":\"\"},{\"line\":191,\"text\":\"\\t\\ttry\"},{\"line\":192,\"text\":\"\\t\\t{\"},{\"line\":193,\"text\":\"\\t\\t\\t$toApply($create);\"},{\"line\":194,\"text\":\"\\t\\t\\t$create->apply();\"},{\"line\":195,\"text\":\"\\t\\t}\"},{\"line\":196,\"text\":\"\\t\\tcatch (\\\\Exception $e)\"},{\"line\":197,\"text\":\"\\t\\t{\"},{\"line\":198,\"text\":\"\\t\\t\\t$this->handleException($e, $tableName, $create);\"},{\"line\":199,\"text\":\"\\t\\t}\"},{\"line\":200,\"text\":\"\\t}\"}]},\"newTable\":{\"ok\":true,\"class\":\"XF\\\\Db\\\\SchemaManager\",\"method\":\"newTable\",\"file\":\"SchemaManager.php\",\"start\":239,\"end\":242,\"sha256\":\"482ad432f7e1304bb4289a1e56fb600d7dfb3708393ec2fd4d6ceba61f8d61de\",\"source\":\"\\tpublic function newTable($tableName)\\n\\t{\\n\\t\\treturn new Create($this->db, $this, $tableName);\\n\\t}\\n\",\"lines\":[{\"line\":239,\"text\":\"\\tpublic function newTable($tableName)\"},{\"line\":240,\"text\":\"\\t{\"},{\"line\":241,\"text\":\"\\t\\treturn new Create($this->db, $this, $tableName);\"},{\"line\":242,\"text\":\"\\t}\"}]},\"handleException\":{\"ok\":true,\"class\":\"XF\\\\Db\\\\SchemaManager\",\"method\":\"handleException\",\"file\":\"SchemaManager.php\",\"start\":254,\"end\":270,\"sha256\":\"bcfbb554306aeb3c108d447c45183c8d6c2415d91e9e785a9671ea1900dbc103\",\"source\":\"\\tprotected function handleException($exception, $tableName, AbstractDdl $ddl)\\n\\t{\\n\\t\\t// The exception might have some extra useful stuff in it, so include attempt to modify the message directly.\\n\\n\\t\\ttry\\n\\t\\t{\\n\\t\\t\\t$reflectionClass = new \\\\ReflectionClass($exception);\\n\\t\\t\\t$messageProperty = $reflectionClass->getProperty('message');\\n\\t\\t\\t$messageProperty->setAccessible(true);\\n\\t\\t\\t$messageProperty->setValue($exception, $tableName . ': ' . $messageProperty->getValue($exception));\\n\\t\\t}\\n\\t\\tcatch (\\\\ReflectionException $ignored)\\n\\t\\t{\\n\\t\\t}\\n\\n\\t\\tthrow $exception;\\n\\t}\\n\",\"lines\":[{\"line\":254,\"text\":\"\\tprotected function handleException($exception, $tableName, AbstractDdl $ddl)\"},{\"line\":255,\"text\":\"\\t{\"},{\"line\":256,\"text\":\"\\t\\t// The exception might have some extra useful stuff in it, so include attempt to modify the message directly.\"},{\"line\":257,\"text\":\"\"},{\"line\":258,\"text\":\"\\t\\ttry\"},{\"line\":259,\"text\":\"\\t\\t{\"},{\"line\":260,\"text\":\"\\t\\t\\t$reflectionClass = new \\\\ReflectionClass($exception);\"},{\"line\":261,\"text\":\"\\t\\t\\t$messageProperty = $reflectionClass->getProperty('message');\"},{\"line\":262,\"text\":\"\\t\\t\\t$messageProperty->setAccessible(true);\"},{\"line\":263,\"text\":\"\\t\\t\\t$messageProperty->setValue($exception, $tableName . ': ' . $messageProperty->getValue($exception));\"},{\"line\":264,\"text\":\"\\t\\t}\"},{\"line\":265,\"text\":\"\\t\\tcatch (\\\\ReflectionException $ignored)\"},{\"line\":266,\"text\":\"\\t\\t{\"},{\"line\":267,\"text\":\"\\t\\t}\"},{\"line\":268,\"text\":\"\"},{\"line\":269,\"text\":\"\\t\\tthrow $exception;\"},{\"line\":270,\"text\":\"\\t}\"}]},\"alterTable\":{\"ok\":true,\"class\":\"XF\\\\Db\\\\SchemaManager\",\"method\":\"alterTable\",\"file\":\"SchemaManager.php\",\"start\":150,\"end\":163,\"sha256\":\"5e9788e5e9344db7c332d6c7e728a050f83967ac6d9d8a06727d266dcbbcc787\",\"source\":\"\\tpublic function alterTable($tableName, \\\\Closure $toApply)\\n\\t{\\n\\t\\t$alter = $this->newAlter($tableName);\\n\\n\\t\\ttry\\n\\t\\t{\\n\\t\\t\\t$toApply($alter);\\n\\t\\t\\t$alter->apply();\\n\\t\\t}\\n\\t\\tcatch (\\\\Exception $e)\\n\\t\\t{\\n\\t\\t\\t$this->handleException($e, $tableName, $alter);\\n\\t\\t}\\n\\t}\\n\",\"lines\":[{\"line\":150,\"text\":\"\\tpublic function alterTable($tableName, \\\\Closure $toApply)\"},{\"line\":151,\"text\":\"\\t{\"},{\"line\":152,\"text\":\"\\t\\t$alter = $this->newAlter($tableName);\"},{\"line\":153,\"text\":\"\"},{\"line\":154,\"text\":\"\\t\\ttry\"},{\"line\":155,\"text\":\"\\t\\t{\"},{\"line\":156,\"text\":\"\\t\\t\\t$toApply($alter);\"},{\"line\":157,\"text\":\"\\t\\t\\t$alter->apply();\"},{\"line\":158,\"text\":\"\\t\\t}\"},{\"line\":159,\"text\":\"\\t\\tcatch (\\\\Exception $e)\"},{\"line\":160,\"text\":\"\\t\\t{\"},{\"line\":161,\"text\":\"\\t\\t\\t$this->handleException($e, $tableName, $alter);\"},{\"line\":162,\"text\":\"\\t\\t}\"},{\"line\":163,\"text\":\"\\t}\"}]},\"renameTable\":{\"ok\":true,\"class\":\"XF\\\\Db\\\\SchemaManager\",\"method\":\"renameTable\",\"file\":\"SchemaManager.php\",\"start\":169,\"end\":181,\"sha256\":\"c352def9c86f9233a9c629670c5334a436092765a9c121807a21ef536510d7db\",\"source\":\"\\tpublic function renameTable($oldTableName, $newTableName)\\n\\t{\\n\\t\\t$alter = $this->newAlter($oldTableName)->renameTo($newTableName);\\n\\n\\t\\ttry\\n\\t\\t{\\n\\t\\t\\t$alter->apply();\\n\\t\\t}\\n\\t\\tcatch (\\\\Exception $e)\\n\\t\\t{\\n\\t\\t\\t$this->handleException($e, $oldTableName, $alter);\\n\\t\\t}\\n\\t}\\n\",\"lines\":[{\"line\":169,\"text\":\"\\tpublic function renameTable($oldTableName, $newTableName)\"},{\"line\":170,\"text\":\"\\t{\"},{\"line\":171,\"text\":\"\\t\\t$alter = $this->newAlter($oldTableName)->renameTo($newTableName);\"},{\"line\":172,\"text\":\"\"},{\"line\":173,\"text\":\"\\t\\ttry\"},{\"line\":174,\"text\":\"\\t\\t{\"},{\"line\":175,\"text\":\"\\t\\t\\t$alter->apply();\"},{\"line\":176,\"text\":\"\\t\\t}\"},{\"line\":177,\"text\":\"\\t\\tcatch (\\\\Exception $e)\"},{\"line\":178,\"text\":\"\\t\\t{\"},{\"line\":179,\"text\":\"\\t\\t\\t$this->handleException($e, $oldTableName, $alter);\"},{\"line\":180,\"text\":\"\\t\\t}\"},{\"line\":181,\"text\":\"\\t}\"}]},\"tableExists\":{\"ok\":true,\"class\":\"XF\\\\Db\\\\SchemaManager\",\"method\":\"tableExists\",\"file\":\"SchemaManager.php\",\"start\":119,\"end\":124,\"sha256\":\"234d0c64067ebbf246972acbed6d58574c535e2ad78478d529afd97963551070\",\"source\":\"\\tpublic function tableExists($tableName)\\n\\t{\\n\\t\\t$status = $this->getTableStatus($tableName);\\n\\n\\t\\treturn $status ? true : false;\\n\\t}\\n\",\"lines\":[{\"line\":119,\"text\":\"\\tpublic function tableExists($tableName)\"},{\"line\":120,\"text\":\"\\t{\"},{\"line\":121,\"text\":\"\\t\\t$status = $this->getTableStatus($tableName);\"},{\"line\":122,\"text\":\"\"},{\"line\":123,\"text\":\"\\t\\treturn $status ? true : false;\"},{\"line\":124,\"text\":\"\\t}\"}]}},\"table_create_class\":\"XF\\\\Db\\\\Schema\\\\Create\",\"table_create_methods\":{\"apply\":{\"ok\":true,\"class\":\"XF\\\\Db\\\\Schema\\\\Create\",\"method\":\"apply\",\"file\":\"AbstractDdl.php\",\"start\":152,\"end\":162,\"sha256\":\"70bf8158872ac741e410f19c8a3893809f6a4514907495ec2fe6af5204446493\",\"source\":\"\\tpublic function apply()\\n\\t{\\n\\t\\t$queries = $this->getQueries();\\n\\n\\t\\tforeach ($queries AS $query)\\n\\t\\t{\\n\\t\\t\\t$this->db->query($query);\\n\\t\\t}\\n\\n\\t\\treturn $queries;\\n\\t}\\n\",\"lines\":[{\"line\":152,\"text\":\"\\tpublic function apply()\"},{\"line\":153,\"text\":\"\\t{\"},{\"line\":154,\"text\":\"\\t\\t$queries = $this->getQueries();\"},{\"line\":155,\"text\":\"\"},{\"line\":156,\"text\":\"\\t\\tforeach ($queries AS $query)\"},{\"line\":157,\"text\":\"\\t\\t{\"},{\"line\":158,\"text\":\"\\t\\t\\t$this->db->query($query);\"},{\"line\":159,\"text\":\"\\t\\t}\"},{\"line\":160,\"text\":\"\"},{\"line\":161,\"text\":\"\\t\\treturn $queries;\"},{\"line\":162,\"text\":\"\\t}\"}]},\"getQueries\":{\"ok\":true,\"class\":\"XF\\\\Db\\\\Schema\\\\Create\",\"method\":\"getQueries\",\"file\":\"Create.php\",\"start\":26,\"end\":110,\"sha256\":\"86696c181f223784f11bf6591fd070796b316648462933706f2702ca20eff475\",\"source\":\"\\tpublic function getQueries()\\n\\t{\\n\\t\\t$tableName = $this->tableName;\\n\\n\\t\\t$queries = [];\\n\\n\\t\\t$query = 'CREATE TABLE';\\n\\n\\t\\tif ($this->checkExists)\\n\\t\\t{\\n\\t\\t\\t$query .= ' IF NOT EXISTS';\\n\\t\\t}\\n\\t\\telse\\n\\t\\t{\\n\\t\\t\\t$existing = $this->db->getSchemaManager()->getTableStatus($tableName);\\n\\t\\t\\tif ($existing)\\n\\t\\t\\t{\\n\\t\\t\\t\\t$existing = new static($this->db, $this->sm, $tableName);\\n\\t\\t\\t\\t$existing->setDefinition();\\n\\n\\t\\t\\t\\tif ($this->compare($existing))\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t// new table is identical, so just skip it\\n\\t\\t\\t\\t\\treturn [];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\telse if ($this->forceChanges)\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t$conflictName = $tableName . '__conflict';\\n\\t\\t\\t\\t\\tif ($this->sm->tableExists($conflictName))\\n\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t$i = 2;\\n\\t\\t\\t\\t\\t\\twhile ($this->sm->tableExists($conflictName . $i))\\n\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t$i++;\\n\\t\\t\\t\\t\\t\\t}\\n\\n\\t\\t\\t\\t\\t\\t$conflictName .= $i;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t$queries[] = \\\"ALTER TABLE `$tableName` RENAME TO `$conflictName`\\\";\\n\\n\\t\\t\\t\\t\\t$errorMessage = sprintf(\\n\\t\\t\\t\\t\\t\\t\\\"Renamed table %s to %s to avoid schema conflict\\\",\\n\\t\\t\\t\\t\\t\\t$tableName,\\n\\t\\t\\t\\t\\t\\t$conflictName\\n\\t\\t\\t\\t\\t);\\n\\n\\t\\t\\t\\t\\t\\\\XF::logError($errorMessage, true);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\telse\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\tthrow new \\\\LogicException(\\\"$tableName already exists, but the structure does not match.\\\");\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\n\\t\\t$query .= \\\" `$tableName` (\\\\n\\\\t\\\";\\n\\n\\t\\t$tableDefinition = [];\\n\\t\\tforeach ($this->addColumns AS $column)\\n\\t\\t{\\n\\t\\t\\t$tableDefinition[] = $column->getDefinition();\\n\\t\\t}\\n\\t\\tforeach ($this->addIndexes AS $index)\\n\\t\\t{\\n\\t\\t\\t$tableDefinition[$index->getIndexName()] = $index->getDefinition();\\n\\t\\t}\\n\\n\\t\\t$query .= implode(\\\",\\\\n\\\\t\\\", $tableDefinition);\\n\\t\\t$query .= \\\"\\\\n)\\\";\\n\\t\\t$query .= ' ' . $this->db->getSchemaManager()->getTableConfigSql($this->engine ?: null);\\n\\n\\t\\tif ($this->comment)\\n\\t\\t{\\n\\t\\t\\t$query .= ' COMMENT=' . $this->db->quote($this->comment);\\n\\t\\t}\\n\\n\\t\\tif ($this->autoIncrementIndex !== null)\\n\\t\\t{\\n\\t\\t\\t$query .= ' AUTO_INCREMENT=' . $this->autoIncrementIndex;\\n\\t\\t}\\n\\n\\t\\t$queries[] = $query;\\n\\n\\t\\treturn $queries;\\n\\t}\\n\",\"lines\":[{\"line\":26,\"text\":\"\\tpublic function getQueries()\"},{\"line\":27,\"text\":\"\\t{\"},{\"line\":28,\"text\":\"\\t\\t$tableName = $this->tableName;\"},{\"line\":29,\"text\":\"\"},{\"line\":30,\"text\":\"\\t\\t$queries = [];\"},{\"line\":31,\"text\":\"\"},{\"line\":32,\"text\":\"\\t\\t$query = 'CREATE TABLE';\"},{\"line\":33,\"text\":\"\"},{\"line\":34,\"text\":\"\\t\\tif ($this->checkExists)\"},{\"line\":35,\"text\":\"\\t\\t{\"},{\"line\":36,\"text\":\"\\t\\t\\t$query .= ' IF NOT EXISTS';\"},{\"line\":37,\"text\":\"\\t\\t}\"},{\"line\":38,\"text\":\"\\t\\telse\"},{\"line\":39,\"text\":\"\\t\\t{\"},{\"line\":40,\"text\":\"\\t\\t\\t$existing = $this->db->getSchemaManager()->getTableStatus($tableName);\"},{\"line\":41,\"text\":\"\\t\\t\\tif ($existing)\"},{\"line\":42,\"text\":\"\\t\\t\\t{\"},{\"line\":43,\"text\":\"\\t\\t\\t\\t$existing = new static($this->db, $this->sm, $tableName);\"},{\"line\":44,\"text\":\"\\t\\t\\t\\t$existing->setDefinition();\"},{\"line\":45,\"text\":\"\"},{\"line\":46,\"text\":\"\\t\\t\\t\\tif ($this->compare($existing))\"},{\"line\":47,\"text\":\"\\t\\t\\t\\t{\"},{\"line\":48,\"text\":\"\\t\\t\\t\\t\\t// new table is identical, so just skip it\"},{\"line\":49,\"text\":\"\\t\\t\\t\\t\\treturn [];\"},{\"line\":50,\"text\":\"\\t\\t\\t\\t}\"},{\"line\":51,\"text\":\"\\t\\t\\t\\telse if ($this->forceChanges)\"},{\"line\":52,\"text\":\"\\t\\t\\t\\t{\"},{\"line\":53,\"text\":\"\\t\\t\\t\\t\\t$conflictName = $tableName . '__conflict';\"},{\"line\":54,\"text\":\"\\t\\t\\t\\t\\tif ($this->sm->tableExists($conflictName))\"},{\"line\":55,\"text\":\"\\t\\t\\t\\t\\t{\"},{\"line\":56,\"text\":\"\\t\\t\\t\\t\\t\\t$i = 2;\"},{\"line\":57,\"text\":\"\\t\\t\\t\\t\\t\\twhile ($this->sm->tableExists($conflictName . $i))\"},{\"line\":58,\"text\":\"\\t\\t\\t\\t\\t\\t{\"},{\"line\":59,\"text\":\"\\t\\t\\t\\t\\t\\t\\t$i++;\"},{\"line\":60,\"text\":\"\\t\\t\\t\\t\\t\\t}\"},{\"line\":61,\"text\":\"\"},{\"line\":62,\"text\":\"\\t\\t\\t\\t\\t\\t$conflictName .= $i;\"},{\"line\":63,\"text\":\"\\t\\t\\t\\t\\t}\"},{\"line\":64,\"text\":\"\\t\\t\\t\\t\\t$queries[] = \\\"ALTER TABLE `$tableName` RENAME TO `$conflictName`\\\";\"},{\"line\":65,\"text\":\"\"},{\"line\":66,\"text\":\"\\t\\t\\t\\t\\t$errorMessage = sprintf(\"},{\"line\":67,\"text\":\"\\t\\t\\t\\t\\t\\t\\\"Renamed table %s to %s to avoid schema conflict\\\",\"},{\"line\":68,\"text\":\"\\t\\t\\t\\t\\t\\t$tableName,\"},{\"line\":69,\"text\":\"\\t\\t\\t\\t\\t\\t$conflictName\"},{\"line\":70,\"text\":\"\\t\\t\\t\\t\\t);\"},{\"line\":71,\"text\":\"\"},{\"line\":72,\"text\":\"\\t\\t\\t\\t\\t\\\\XF::logError($errorMessage, true);\"},{\"line\":73,\"text\":\"\\t\\t\\t\\t}\"},{\"line\":74,\"text\":\"\\t\\t\\t\\telse\"},{\"line\":75,\"text\":\"\\t\\t\\t\\t{\"},{\"line\":76,\"text\":\"\\t\\t\\t\\t\\tthrow new \\\\LogicException(\\\"$tableName already exists, but the structure does not match.\\\");\"},{\"line\":77,\"text\":\"\\t\\t\\t\\t}\"},{\"line\":78,\"text\":\"\\t\\t\\t}\"},{\"line\":79,\"text\":\"\\t\\t}\"},{\"line\":80,\"text\":\"\"},{\"line\":81,\"text\":\"\\t\\t$query .= \\\" `$tableName` (\\\\n\\\\t\\\";\"},{\"line\":82,\"text\":\"\"},{\"line\":83,\"text\":\"\\t\\t$tableDefinition = [];\"},{\"line\":84,\"text\":\"\\t\\tforeach ($this->addColumns AS $column)\"},{\"line\":85,\"text\":\"\\t\\t{\"},{\"line\":86,\"text\":\"\\t\\t\\t$tableDefinition[] = $column->getDefinition();\"},{\"line\":87,\"text\":\"\\t\\t}\"},{\"line\":88,\"text\":\"\\t\\tforeach ($this->addIndexes AS $index)\"},{\"line\":89,\"text\":\"\\t\\t{\"},{\"line\":90,\"text\":\"\\t\\t\\t$tableDefinition[$index->getIndexName()] = $index->getDefinition();\"},{\"line\":91,\"text\":\"\\t\\t}\"},{\"line\":92,\"text\":\"\"},{\"line\":93,\"text\":\"\\t\\t$query .= implode(\\\",\\\\n\\\\t\\\", $tableDefinition);\"},{\"line\":94,\"text\":\"\\t\\t$query .= \\\"\\\\n)\\\";\"},{\"line\":95,\"text\":\"\\t\\t$query .= ' ' . $this->db->getSchemaManager()->getTableConfigSql($this->engine ?: null);\"},{\"line\":96,\"text\":\"\"},{\"line\":97,\"text\":\"\\t\\tif ($this->comment)\"},{\"line\":98,\"text\":\"\\t\\t{\"},{\"line\":99,\"text\":\"\\t\\t\\t$query .= ' COMMENT=' . $this->db->quote($this->comment);\"},{\"line\":100,\"text\":\"\\t\\t}\"},{\"line\":101,\"text\":\"\"},{\"line\":102,\"text\":\"\\t\\tif ($this->autoIncrementIndex !== null)\"},{\"line\":103,\"text\":\"\\t\\t{\"},{\"line\":104,\"text\":\"\\t\\t\\t$query .= ' AUTO_INCREMENT=' . $this->autoIncrementIndex;\"},{\"line\":105,\"text\":\"\\t\\t}\"},{\"line\":106,\"text\":\"\"},{\"line\":107,\"text\":\"\\t\\t$queries[] = $query;\"},{\"line\":108,\"text\":\"\"},{\"line\":109,\"text\":\"\\t\\treturn $queries;\"},{\"line\":110,\"text\":\"\\t}\"}]},\"getCreateQuery\":{\"ok\":false,\"class\":\"XF\\\\Db\\\\Schema\\\\Create\",\"method\":\"getCreateQuery\",\"error\":\"ReflectionException\"},\"exists\":{\"ok\":false,\"class\":\"XF\\\\Db\\\\Schema\\\\Create\",\"method\":\"exists\",\"error\":\"ReflectionException\"}},\"source_scans\":[{\"file\":\"src/XF/Cli/Command/AddOnActionTrait.php\",\"sha256\":\"265c7bd3e5dbeb5669b52e57fc9c67411261be00e493cc717aa6b5c991421287\",\"hits\":[{\"line\":15,\"text\":\"use XF\\\\AddOn\\\\StepResult;\"},{\"line\":118,\"text\":\"/** @var StepResult $result */\"},{\"line\":131,\"text\":\"$params['step'] = $result->step;\"},{\"line\":219,\"text\":\"'xf:addon-sub-action',\"}]},{\"file\":\"src/XF/Cli/Command/AddOnInstall.php\",\"sha256\":\"2407ad9ae20ca8ac1ca84b456ac2adc537f39c79534da5e258167a4d0df2a54f\",\"hits\":[{\"line\":20,\"text\":\"->setName('xf:addon-install')\"}]},{\"file\":\"src/XF/Cli/Command/AddOnList.php\",\"sha256\":\"3047ffa03d4fa488cb8a53c2f0c8c88edd8372e5804340f72b3fd761b7eff1ea\",\"hits\":[{\"line\":136,\"text\":\"'last_pending_action' => $installed->last_pending_action,\"},{\"line\":198,\"text\":\"$installed->last_pending_action ?: '-',\"}]},{\"file\":\"src/XF/Cli/Command/AddOnSubAction.php\",\"sha256\":\"4cbf315edc17bf5773c624da2d1af076f47dd588398462d657f709d832adbb46\",\"hits\":[{\"line\":18,\"text\":\"->setName('xf:addon-sub-action')\"},{\"line\":19,\"text\":\"->setDescription('Runs a add-on sub-action in a separate process. Do not run directly!')\"},{\"line\":46,\"text\":\"$output->writeln(\\\"Invalid sub-action confirmation key. Run from parent command.\\\");\"}]},{\"file\":\"src/XF/Cli/Command/Import.php\",\"sha256\":\"cbc8b5707e84a1b1293ca00f57dcc91bb0ded0d3810eb976d0b93327c1dd32f5\",\"hits\":[{\"line\":14,\"text\":\"use XF\\\\Import\\\\StepState;\"},{\"line\":39,\"text\":\"'If set, the import will be automatically finalized when the data import step completes.'\"},{\"line\":112,\"text\":\"function ($isComplete, $step, StepState $stepState, $importCompletion) use ($progressIndicator, &$progressStarted)\"},{\"line\":114,\"text\":\"$stepTitle = $stepState->title;\"},{\"line\":115,\"text\":\"if (!$stepTitle)\"},{\"line\":132,\"text\":\"$stepNumberStrlen = strlen((string) $importCompletion['total']);\"},{\"line\":133,\"text\":\"$stepNameStrlen = 25; // just arbitrary for now, but could be based on the strlen of the longest step title\"},{\"line\":135,\"text\":\"$stepInfo = sprintf(\"},{\"line\":136,\"text\":\"\\\"Step %{$stepNumberStrlen}d of %d: %-{$stepNameStrlen}s \\\",\"},{\"line\":139,\"text\":\"$stepTitle\"},{\"line\":142,\"text\":\"if ($stepState->complete)\"},{\"line\":145,\"text\":\"$stepInfo\"},{\"line\":146,\"text\":\". $this->getIntervalString($stepState->startDate, $stepState->completeDate)\"},{\"line\":147,\"text\":\". ' [' . \\\\XF::language()->numberFormat($stepState->imported) . ']'\"},{\"line\":154,\"text\":\"$stepInfo\"},{\"line\":155,\"text\":\". $this->getIntervalString($stepState->startDate, time()) . ' '\"},{\"line\":156,\"text\":\". $stepState->getCompletionOutput()\"}]},{\"file\":\"src/XF/Cli/Command/ImportChildProcess.php\",\"sha256\":\"4018331a7104801b8d7c73c6bf90374e198ed576897a7b4b01e5195c9d5133f9\",\"hits\":[{\"line\":24,\"text\":\"'step',\"},{\"line\":26,\"text\":\"'The name of the step to run.'\"},{\"line\":63,\"text\":\"$step = $input->getArgument('step');\"},{\"line\":67,\"text\":\"if (!$runner->validateChildProcessRun($step, $startAfter, $end, $error))\"},{\"line\":78,\"text\":\"$runner->runChildProcess($step, $startAfter, $end, $messageReceiver);\"}]},{\"file\":\"src/XF/Cli/Command/ImportCommandTrait.php\",\"sha256\":\"a4816d99b66aa795a1558e01dc42169c471af78028e103533326ced8365f970b\",\"hits\":[{\"line\":21,\"text\":\"$totalsTable->setHeaders(['Step', 'Total', 'Time taken']);\"}]},{\"file\":\"src/XF/Cli/Command/ImportFinalize.php\",\"sha256\":\"78b8ed78256f621c461fe11a6b206a3871819c9960660029feb8d76134ecfde8\",\"hits\":[{\"line\":64,\"text\":\"$jobs = $manager->getImporter($session->importerId)->getFinalizeJobs($session->getStepsRun());\"}]},{\"file\":\"src/XF/Cli/Command/Upgrade.php\",\"sha256\":\"9f58a531299befbb84458add55bb9e701fc18cd06f49d5c86c15fd5871af1a61\",\"hits\":[{\"line\":70,\"text\":\". ($lastUpgradeVersion['last_step'] ? \\\" (step $lastUpgradeVersion[last_step])\\\" : '')\"},{\"line\":75,\"text\":\"$upgradeComplete = ($lastUpgradeVersion['version_id'] === \\\\XF::$versionId && !$lastUpgradeVersion['last_step']);\"},{\"line\":104,\"text\":\"$step = 1;\"},{\"line\":106,\"text\":\"if ($lastUpgradeVersion['last_step'])\"},{\"line\":109,\"text\":\"$step = $lastUpgradeVersion['last_step'] + 1;\"},{\"line\":115,\"text\":\"$step = 1;\"},{\"line\":126,\"text\":\"$upgrader->assertValidUpgradeSteps($upgrade);\"},{\"line\":132,\"text\":\"while (method_exists($upgrade, 'step' . $step))\"},{\"line\":136,\"text\":\"$this->outputStatus($output, \\\"Running upgrade to $versionName, step $step ($position)...\\\");\"},{\"line\":140,\"text\":\"$this->outputStatus($output, \\\"Running upgrade to $versionName, step $step...\\\");\"},{\"line\":143,\"text\":\"$result = $upgrade->{'step' . $step}($position, $data, $controller);\"},{\"line\":146,\"text\":\"$this->clearStatus($output, 'This step must be completed via the web interface.');\"},{\"line\":151,\"text\":\"$this->clearStatus($output, \\\"Running upgrade to $versionName, step $step... done.\\\");\"},{\"line\":156,\"text\":\"$upgrader->insertUpgradeLog($runVersionId, $step);\"},{\"line\":158,\"text\":\"$this->clearStatus($output, \\\"Running upgrade to $versionName, step $step... done.\\\");\"},{\"line\":160,\"text\":\"$step++;\"},{\"line\":166,\"text\":\"// stay on the same step\"},{\"line\":172,\"text\":\"$this->clearStatus($output, 'The upgrade step returned an unexpected result.');\"},{\"line\":180,\"text\":\"$step = 1;\"},{\"line\":184,\"text\":\"$output->writeln(['All upgrade steps run up to version ' . \\\\XF::$version . '.', '']);\"}]},{\"file\":\"src/XF/Cli/Command/AddOn/AbstractSetupStep.php\",\"sha256\":\"86ac6e9eda2202a75f3566a6bf20b14b5cc5171a823e0a23de0e66d0e8c0a8b7\",\"hits\":[{\"line\":9,\"text\":\"use XF\\\\AddOn\\\\StepResult;\"},{\"line\":16,\"text\":\"abstract class AbstractSetupStep extends AbstractCommand\"},{\"line\":21,\"text\":\"abstract protected function getStepType();\"},{\"line\":27,\"text\":\"$command = $this->getStepType();\"},{\"line\":30,\"text\":\"->setName('xf-addon:' . $command . '-step')\"},{\"line\":31,\"text\":\"->setDescription('Runs a specific step from the specified add-on Setup class.')\"},{\"line\":60,\"text\":\"$step = $input->getArgument('step');\"},{\"line\":64,\"text\":\"$stepType = $this->getStepType();\"},{\"line\":65,\"text\":\"if ($stepType == 'upgrade')\"},{\"line\":70,\"text\":\"$setup->prepareForAction($stepType);\"},{\"line\":74,\"text\":\"$result = $this->runStep($setup, $output, $stepType, $step, $version, $params);\"},{\"line\":75,\"text\":\"if (!($result instanceof StepResult))\"},{\"line\":77,\"text\":\"$this->clearStatus($output, \\\"Must return a StepResult object.\\\");\"},{\"line\":104,\"text\":\"protected function runStep(AbstractSetup $setup, OutputInterface $output, $stepType, $step, $version = null, array $params = [])\"},{\"line\":106,\"text\":\"$method = $stepType;\"},{\"line\":112,\"text\":\"if ($step)\"},{\"line\":114,\"text\":\"$method .= 'Step' . $step;\"},{\"line\":119,\"text\":\"if ($version && $step)\"},{\"line\":121,\"text\":\"$method .= $version . 'Step' . $step;\"},{\"line\":129,\"text\":\"return new StepResult(true);\"},{\"line\":137,\"text\":\"$result = new StepResult(true);\"},{\"line\":142,\"text\":\"$result = new StepResult(false, $result);\"}]},{\"file\":\"src/XF/Cli/Command/AddOn/Create.php\",\"sha256\":\"4ff8f77caa12327158b9a6ba6ed2ffe85b959011279be5a70a8b3e77f75204f5\",\"hits\":[{\"line\":217,\"text\":\"$question = new ConfirmationQuestion(\\\"Does your Setup need to support running multiple steps? (y/n) \\\");\"},{\"line\":226,\"text\":\"use XF\\\\AddOn\\\\StepRunnerInstallTrait;\"},{\"line\":227,\"text\":\"use XF\\\\AddOn\\\\StepRunnerUninstallTrait;\"},{\"line\":228,\"text\":\"use XF\\\\AddOn\\\\StepRunnerUpgradeTrait;\"},{\"line\":232,\"text\":\"use StepRunnerInstallTrait;\"},{\"line\":233,\"text\":\"use StepRunnerUpgradeTrait;\"},{\"line\":234,\"text\":\"use StepRunnerUninstallTrait;\"},{\"line\":250,\"text\":\"public function install(array \\\\$stepParams = [])\"},{\"line\":255,\"text\":\"public function upgrade(array \\\\$stepParams = [])\"},{\"line\":260,\"text\":\"public function uninstall(array \\\\$stepParams = [])\"},{\"line\":283,\"text\":\"$output->writeln(\\\"If you change your mind, create a file named Setup.php in \\\" . dirname($setupPath) . \\\" which should extend AbstractSetup and optionally use one of the StepRunnerX traits.\\\");\"}]},{\"file\":\"src/XF/Cli/Command/AddOn/InstallStep.php\",\"sha256\":\"5536a7cdaa190b8ddff16e58733a546c3735ae8e55ab4c9d3cf1e1acce615ca2\",\"hits\":[{\"line\":7,\"text\":\"class InstallStep extends AbstractSetupStep\"},{\"line\":9,\"text\":\"protected function getStepType()\"},{\"line\":17,\"text\":\"'step',\"},{\"line\":19,\"text\":\"'The step number to run.'\"}]},{\"file\":\"src/XF/Cli/Command/AddOn/UninstallStep.php\",\"sha256\":\"d69b287acd3ea5c02bf23492e1bdef465fb75f22f00b45acdb4ffafe547260e5\",\"hits\":[{\"line\":7,\"text\":\"class UninstallStep extends AbstractSetupStep\"},{\"line\":9,\"text\":\"protected function getStepType()\"},{\"line\":17,\"text\":\"'step',\"},{\"line\":19,\"text\":\"'The step number to run.'\"}]},{\"file\":\"src/XF/Cli/Command/AddOn/UpgradeStep.php\",\"sha256\":\"51d6bcea38a819ab7a983340112de1b9778ed9efeb0a139f8d0b6c967b4e052f\",\"hits\":[{\"line\":7,\"text\":\"class UpgradeStep extends AbstractSetupStep\"},{\"line\":9,\"text\":\"protected function getStepType()\"},{\"line\":23,\"text\":\"'step',\"},{\"line\":25,\"text\":\"'The step number to run.'\"}]},{\"file\":\"src/XF/Cli/Command/Rebuild/AbstractRebuildCommand.php\",\"sha256\":\"9b019518b8fb2d2e3bf6d281acb57e181c4b48f2acbf654efdc81b87f294c7f4\",\"hits\":[{\"line\":56,\"text\":\"'resume',\"},{\"line\":73,\"text\":\"if ($input->getOption('resume'))\"},{\"line\":81,\"text\":\"$output->writeln(\\\"There are no pending jobs of this type to resume.\\\");\"}]},{\"file\":\"src/XF/Cli/Command/EmbedMetadata/AbstractEmbedMetadataCommand.php\",\"sha256\":\"d58bdc8eb04615e12b7838403db010fb05ff9238203467061fd7f0bb2d6274f9\",\"hits\":[{\"line\":74,\"text\":\"'resume',\"},{\"line\":77,\"text\":\"'Resume an existing pending job instead of starting a new one. Without this flag, re-running the command discards any prior progress and restarts from the beginning.'\"},{\"line\":92,\"text\":\"if ($input->getOption('resume'))\"},{\"line\":100,\"text\":\"$output->writeln(\\\"There are no pending jobs of this type to resume.\\\");\"}]},{\"file\":\"src/XF/Cli/Command/Development/UpgradeStep.php\",\"sha256\":\"6c91e119b41e5d2b83da72f7d37c02ff2f3d6149b7b7974e05ab3539f0e59fd5\",\"hits\":[{\"line\":18,\"text\":\"class UpgradeStep extends AbstractCommand implements CustomAppCommandInterface\"},{\"line\":30,\"text\":\"->setName('xf-dev:upgrade-step')\"},{\"line\":31,\"text\":\"->setDescription('Runs a specific upgrade step from a specified upgrade class.')\"},{\"line\":38,\"text\":\"'step',\"},{\"line\":40,\"text\":\"'The step number to run'\"},{\"line\":54,\"text\":\"$step = $input->getArgument('step');\"},{\"line\":60,\"text\":\"$returnCode = $this->runStep($upgrade, $output, $controller, $step, $position, $data);\"},{\"line\":73,\"text\":\"throw new \\\\LogicException(\\\"Step did not return an expected result\\\");\"},{\"line\":81,\"text\":\"protected function runStep(AbstractUpgrade $upgrade, OutputInterface $output, Upgrade $controller, $step, $position = 0, $data = [])\"},{\"line\":85,\"text\":\"if (!method_exists($upgrade, 'step' . $step))\"},{\"line\":87,\"text\":\"$this->clearStatus($output, \\\"Upgrade to version $versionName does not have a step$step() method.\\\");\"},{\"line\":93,\"text\":\"$this->outputStatus($output, \\\"Running upgrade to $versionName, step $step ($position)...\\\");\"},{\"line\":97,\"text\":\"$this->outputStatus($output, \\\"Running upgrade to $versionName, step $step...\\\");\"},{\"line\":100,\"text\":\"$result = $upgrade->{'step' . $step}($position, $data, $controller);\"},{\"line\":103,\"text\":\"$this->clearStatus($output, \\\"This step must be completed via the web interface.\\\");\"},{\"line\":108,\"text\":\"$this->clearStatus($output, \\\"Running upgrade to $versionName, step $step... done.\\\");\"},{\"line\":113,\"text\":\"// stay on the same step\"},{\"line\":118,\"text\":\"$this->clearStatus($output, \\\"The upgrade step returned an unexpected result.\\\");\"}]},{\"file\":\"src/XF/AddOn/AbstractSetup.php\",\"sha256\":\"6bdd3fe834e15b963a52c9357f54262f2d12f3c7c3686fc31333b549cddf2d88\",\"hits\":[{\"line\":21,\"text\":\"* @param array $stepParams\"},{\"line\":23,\"text\":\"* @return null|StepResult\"},{\"line\":25,\"text\":\"abstract public function install(array $stepParams = []);\"},{\"line\":28,\"text\":\"* @param array $stepParams\"},{\"line\":30,\"text\":\"* @return null|StepResult\"},{\"line\":32,\"text\":\"abstract public function upgrade(array $stepParams = []);\"},{\"line\":35,\"text\":\"* @param array $stepParams\"},{\"line\":37,\"text\":\"* @return null|StepResult\"},{\"line\":39,\"text\":\"abstract public function uninstall(array $stepParams = []);\"}]},{\"file\":\"src/XF/AddOn/AddOn.php\",\"sha256\":\"0e0346a046fff6bde9850cb53e9dc0d0b5379387029dc16925e562fa141ab422\",\"hits\":[{\"line\":346,\"text\":\"$lastAction = $this->installedAddOn->getLastActionStep('install');\"},{\"line\":349,\"text\":\"// we haven't completed the install steps yet, don't consider as installed\"},{\"line\":537,\"text\":\"public function updatePendingAction($action, $step)\"},{\"line\":541,\"text\":\"$this->installedAddOn->fastUpdate('last_pending_action', \\\"$action:$step\\\");\"},{\"line\":549,\"text\":\"$this->installedAddOn->fastUpdate('last_pending_action', null);\"},{\"line\":568,\"text\":\"'last_pending_action' => 'install:0',\"},{\"line\":653,\"text\":\"$installed->last_pending_action = 'uninstall:0';\"}]},{\"file\":\"src/XF/AddOn/StepResult.php\",\"sha256\":\"d486646b6b20370f7c03f473468ecec93e7cea3ef45cca8d72d6fe9b2701f9be\",\"hits\":[{\"line\":5,\"text\":\"class StepResult\"},{\"line\":9,\"text\":\"public $step;\"},{\"line\":12,\"text\":\"public function __construct($complete, array $params = [], $step = null, $version = null)\"},{\"line\":16,\"text\":\"$this->step = $step;\"}]},{\"file\":\"src/XF/AddOn/StepRunnerInstallTrait.php\",\"sha256\":\"1f441b8a3101b97009ae04e62c04e79062a89f1e01a08ae9e07c5e629c76d5f2\",\"hits\":[{\"line\":10,\"text\":\"trait StepRunnerInstallTrait\"},{\"line\":13,\"text\":\"* @param array $stepParams\"},{\"line\":15,\"text\":\"* @return null|StepResult\"},{\"line\":17,\"text\":\"public function install(array $stepParams = [])\"},{\"line\":19,\"text\":\"$stepParams = array_replace([\"},{\"line\":20,\"text\":\"'step' => 0,\"},{\"line\":21,\"text\":\"], $stepParams);\"},{\"line\":23,\"text\":\"$step = $stepParams['step'];\"},{\"line\":24,\"text\":\"if (!$step)\"},{\"line\":26,\"text\":\"$step = $this->getInstallResumeStep();\"},{\"line\":29,\"text\":\"return $this->installStepRunner($step, $stepParams);\"},{\"line\":32,\"text\":\"private function getInstallResumeStep()\"},{\"line\":37,\"text\":\"$lastActionStep = $installedAddOn->getLastActionStep('install');\"},{\"line\":38,\"text\":\"if ($lastActionStep)\"},{\"line\":40,\"text\":\"return $lastActionStep + 1; // this is the last completed step, so resume with the next\"},{\"line\":48,\"text\":\"* @param integer $step\"},{\"line\":49,\"text\":\"* @param array $stepParams\"},{\"line\":51,\"text\":\"* @return null|StepResult\"},{\"line\":53,\"text\":\"private function installStepRunner($step, array $stepParams)\"},{\"line\":55,\"text\":\"$fnPrefix = 'installStep';\"},{\"line\":56,\"text\":\"$fn = $fnPrefix . $step;\"},{\"line\":62,\"text\":\"$result = $this->$fn($stepParams);\"},{\"line\":65,\"text\":\"$result = new StepResult(true);\"},{\"line\":69,\"text\":\"$result = new StepResult(false, $result);\"},{\"line\":72,\"text\":\"if (!($result instanceof StepResult))\"},{\"line\":74,\"text\":\"throw new \\\\LogicException(\\\"Must return a StepResult object\\\");\"},{\"line\":77,\"text\":\"$result->step = $step;\"},{\"line\":81,\"text\":\"$this->addOn->updatePendingAction('install', $result->step);\"},{\"line\":83,\"text\":\"$nextStep = $step + 1;\"},{\"line\":84,\"text\":\"$nextFn = $fnPrefix . $nextStep;\"},{\"line\":90,\"text\":\"$result = new StepResult(false, [], $nextStep);\"}]},{\"file\":\"src/XF/AddOn/StepRunnerUninstallTrait.php\",\"sha256\":\"e58a9ab9c30e3cf3c41a0be392e8c5ac37f744578f7b91f76d663139649c49a9\",\"hits\":[{\"line\":10,\"text\":\"trait StepRunnerUninstallTrait\"},{\"line\":13,\"text\":\"* @param array $stepParams\"},{\"line\":15,\"text\":\"* @return null|StepResult\"},{\"line\":17,\"text\":\"public function uninstall(array $stepParams = [])\"},{\"line\":19,\"text\":\"$stepParams = array_replace([\"},{\"line\":20,\"text\":\"'step' => 0,\"},{\"line\":21,\"text\":\"], $stepParams);\"},{\"line\":23,\"text\":\"$step = $stepParams['step'];\"},{\"line\":24,\"text\":\"if (!$step)\"},{\"line\":26,\"text\":\"$step = $this->getUninstallResumeStep();\"},{\"line\":28,\"text\":\"return $this->uninstallStepRunner($step, $stepParams);\"},{\"line\":31,\"text\":\"private function getUninstallResumeStep()\"},{\"line\":36,\"text\":\"$lastActionStep = $installedAddOn->getLastActionStep('uninstall');\"},{\"line\":37,\"text\":\"if ($lastActionStep)\"},{\"line\":39,\"text\":\"return $lastActionStep + 1; // this is the last completed step, so resume with the next\"},{\"line\":47,\"text\":\"* @param integer $step\"},{\"line\":48,\"text\":\"* @param array $stepParams\"},{\"line\":50,\"text\":\"* @return null|StepResult\"},{\"line\":52,\"text\":\"private function uninstallStepRunner($step, array $stepParams)\"},{\"line\":54,\"text\":\"$fnPrefix = 'uninstallStep';\"},{\"line\":55,\"text\":\"$fn = $fnPrefix . $step;\"},{\"line\":61,\"text\":\"$result = $this->$fn($stepParams);\"},{\"line\":64,\"text\":\"$result = new StepResult(true);\"},{\"line\":68,\"text\":\"$result = new StepResult(false, $result);\"},{\"line\":71,\"text\":\"if (!($result instanceof StepResult))\"},{\"line\":73,\"text\":\"throw new \\\\LogicException(\\\"Must return a StepResult object\\\");\"},{\"line\":76,\"text\":\"$result->step = $step;\"},{\"line\":80,\"text\":\"$this->addOn->updatePendingAction('uninstall', $result->step);\"},{\"line\":82,\"text\":\"$nextStep = $step + 1;\"},{\"line\":83,\"text\":\"$nextFn = $fnPrefix . $nextStep;\"},{\"line\":89,\"text\":\"$result = new StepResult(false, [], $nextStep);\"}]},{\"file\":\"src/XF/AddOn/StepRunnerUpgradeTrait.php\",\"sha256\":\"b61698d9c20f094cc1b704ad48798148fe5843e2dc746592cb2db252b579d1b5\",\"hits\":[{\"line\":10,\"text\":\"trait StepRunnerUpgradeTrait\"},{\"line\":13,\"text\":\"* @param array $stepParams\"},{\"line\":15,\"text\":\"* @return null|StepResult\"},{\"line\":17,\"text\":\"public function upgrade(array $stepParams = [])\"},{\"line\":19,\"text\":\"$stepParams = $this->getStepParams($stepParams);\"},{\"line\":22,\"text\":\"$stepsGrouped = [];\"},{\"line\":27,\"text\":\"if (preg_match('/^upgrade(\\\\d+)Step(\\\\d+)$/', $method->name, $match))\"},{\"line\":30,\"text\":\"$step = intval($match[2]);\"},{\"line\":33,\"text\":\"$stepsGrouped[$versionId][$step] = $step;\"},{\"line\":42,\"text\":\"if (!$stepParams['version_id'])\"},{\"line\":44,\"text\":\"$resume = $this->getUpgradeResumeStep();\"},{\"line\":45,\"text\":\"$stepParams['version_id'] = $resume[0];\"},{\"line\":46,\"text\":\"$stepParams['step'] = $resume[1];\"},{\"line\":49,\"text\":\"$runStep = $stepParams['step'];\"},{\"line\":50,\"text\":\"if (!$runStep)\"},{\"line\":52,\"text\":\"$runStep = 1;\"},{\"line\":60,\"text\":\"if ($versionId >= $stepParams['version_id'])\"},{\"line\":62,\"text\":\"$versionSteps = $stepsGrouped[$versionId];\"},{\"line\":63,\"text\":\"if (isset($versionSteps[$runStep]))\"},{\"line\":65,\"text\":\"if ($versionId != $stepParams['version_id'] || $runStep != $stepParams['step'])\"},{\"line\":67,\"text\":\"// sanity check - don't pass params if we're changing versions or steps\"},{\"line\":68,\"text\":\"$stepParams = [];\"},{\"line\":73,\"text\":\"return $this->upgradeStepRunner($versionId, $runStep, $stepParams, $nextVersionId);\"},{\"line\":76,\"text\":\"// if we hit here, then the step couldn't be found, so move onto the next upgrade\"},{\"line\":77,\"text\":\"$runStep = 1;\"},{\"line\":78,\"text\":\"$stepParams = $this->getStepParams();\"},{\"line\":86,\"text\":\"protected function getStepParams(array $stepParams = [])\"},{\"line\":90,\"text\":\"'step' => 0,\"},{\"line\":91,\"text\":\"], $stepParams);\"},{\"line\":94,\"text\":\"private function getUpgradeResumeStep()\"},{\"line\":97,\"text\":\"$lastActionStep = $installedAddOn->getLastActionStep('upgrade');\"},{\"line\":98,\"text\":\"if ($lastActionStep)\"},{\"line\":100,\"text\":\"$lastActionStep[1]++; // we completed this step, so need to resume with the next\"},{\"line\":101,\"text\":\"return $lastActionStep;\"},{\"line\":109,\"text\":\"* @param integer $runStep\"},{\"line\":110,\"text\":\"* @param array $stepParams\"},{\"line\":113,\"text\":\"* @return null|StepResult\"},{\"line\":115,\"text\":\"private function upgradeStepRunner($runVersion, $runStep, array $stepParams, $nextVersionId)\"},{\"line\":117,\"text\":\"$fnPattern = 'upgrade%dStep%d';\"},{\"line\":118,\"text\":\"$fn = sprintf($fnPattern, $runVersion, $runStep);\"},{\"line\":121,\"text\":\"throw new \\\\LogicException(\\\"Step $fn doesn't exist. Should have been checked earlier.\\\");\"},{\"line\":124,\"text\":\"$result = $this->$fn($stepParams);\"},{\"line\":127,\"text\":\"$result = new StepResult(true);\"},{\"line\":131,\"text\":\"$result = new StepResult(false, $result);\"},{\"line\":134,\"text\":\"if (!($result instanceof StepResult))\"},{\"line\":136,\"text\":\"throw new \\\\LogicException(\\\"Must return a StepResult object\\\");\"},{\"line\":139,\"text\":\"$result->step = $runStep;\"},{\"line\":144,\"text\":\"$this->addOn->updatePendingAction('upgrade', $result->version . ':' . $result->step);\"},{\"line\":146,\"text\":\"$nextStep = $runStep + 1;\"},{\"line\":147,\"text\":\"$nextStepFn = sprintf($fnPattern, $runVersion, $nextStep);\"},{\"line\":148,\"text\":\"if (method_exists($this, $nextStepFn))\"},{\"line\":150,\"text\":\"$result = new StepResult(false, [], $nextStep, $runVersion);\"},{\"line\":166,\"text\":\"$result = new StepResult(false, [], 1, $nextVersionId);\"}]},{\"file\":\"src/XF/AddOn/DataType/AbstractDataType.php\",\"sha256\":\"a4f6ec14e4009be0029548b07272dc77c6ad96f4cca4e067a7d3ea0004126815\",\"hits\":[{\"line\":165,\"text\":\"protected function resume($maxRunTime, $startTime)\"}]}]},\"assessment\":{\"all_six_tables_present\":true,\"all_six_tables_empty\":true,\"duplicate_create_appears_safe\":true,\"native_resume_signal\":true},\"policy\":{\"delete_performed\":false,\"mutation_performed\":false,\"goal\":\"select a no-delete native or bounded bridge install path\"}}\nGRAM513R3R3_DECISION=PASS_NATIVE_RESUME_SCHEMA_RCA\nGRAM513R3R3_NEXT_GATE=READY_FOR_DIRECT_NATIVE_RETRY_CANARY_513R3R4\nHOMELAB_RESULT_CONTRACT={\"version\":1,\"command_id\":\"SUPPORT-260918-GRAM-XF-CODEVIPE-NATIVE-RESUME-SCHEMA-RCA-513R3R3\",\"status\":\"OK\",\"changes_made\":false,\"rollback_started\":false,\"rollback_restored\":null}\n" } diff --git a/runtime/latest.txt b/runtime/latest.txt index 4a3cf94e..a8a41087 100644 --- a/runtime/latest.txt +++ b/runtime/latest.txt @@ -1,15 +1,15 @@ CHAT_OUTPUT_BEGIN -COMMAND_ID=SUPPORT-260918-GRAM-XF-CODEVIPE-PARTIAL-STATE-INSTALLABILITY-RCA-513R3R2 +COMMAND_ID=SUPPORT-260918-GRAM-XF-CODEVIPE-NATIVE-RESUME-SCHEMA-RCA-513R3R3 STATUS=OK RC=0 HOST=pve01 MODE=read-only -COMPONENT=gram-support-codevipe-partial-state-installability-rca +COMPONENT=gram-support-codevipe-native-resume-schema-rca REFERENCE_REGISTER_CHECK=OK REFERENCE_SHA256=5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66 ERROR_REGISTER_CHECK=OK ERROR_REGISTER_SHA256=3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0 -COMMAND_SHA256=2007a08bdd3a7e3c5541e130c8f14d46a334da28d493dc7aaa74707f6ed4d2b7 +COMMAND_SHA256=d024725d107ae38e09893a322f7a365399e215a929d3c723a3099129609390bf DUPLICATE_FAILED_COMMAND_BLOCKED=false EXECUTION_STARTED=true CHANGE_DECLARED=false @@ -24,17 +24,17 @@ MUTATION_OUTCOME=NO_MUTATION SANITIZED=yes SECRETS_INCLUDED=no PRIVATE_ADDRESSES_INCLUDED=no -RAW_EVIDENCE_SHA256=f8164218838f14dc4258bebe0143a275376e0dd5cd30c7c34d38151d3b94a72d -SANITIZED_OUTPUT_SHA256=f8164218838f14dc4258bebe0143a275376e0dd5cd30c7c34d38151d3b94a72d +RAW_EVIDENCE_SHA256=3356fd66c51344f1c1c25279dd2f3ad70b12040178c3a7513b0aa812b569ae94 +SANITIZED_OUTPUT_SHA256=3356fd66c51344f1c1c25279dd2f3ad70b12040178c3a7513b0aa812b569ae94 OUTPUT_BEGIN -GRAM513R3R2_WRAPPER_BEGIN=true +GRAM513R3R3_WRAPPER_BEGIN=true ERROR_REGISTER_CHECK=OK REFERENCE_CHECK=OK AUTHORITY_CHECK_SCOPE=READABILITY_ONLY_INCIDENTS_NOT_CLOSED -GRAM513R3R2_SAFE_REPORT={"artifact":{"sha256":"2e31f89d3626a83c1211910aa6fd279cc04689b75ba822899952865085cf551e","version_id":1000120,"version_string":"1.0.0 Alpha 3 Unified Fix 10","setup_sha256":"4977f90ec0444e2e3a1e4ee9b79a4e88098c5a3ae37b30d63e77cff2e1fcb971","template_modifications_sha256":"04f338a8107a80bd3c17b6f6888faea596a5057140556ce6f4f1673d2034628b"},"setup_hits":[{"line":15,"text":"public function installStep1(): void","context":" use StepRunnerUninstallTrait;\\n\\n public function installStep1(): void\\n {\\n $sm = $this->schemaManager();\\n $sm->createTable('xf_gram_support_ticket', function($table) {"},{"line":17,"text":"$sm = $this->schemaManager();","context":" public function installStep1(): void\\n {\\n $sm = $this->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);"},{"line":18,"text":"$sm->createTable('xf_gram_support_ticket', function($table) {","context":" {\\n $sm = $this->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);"},{"line":44,"text":"$sm->createTable('xf_gram_support_message', function($table) {","context":" $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);"},{"line":56,"text":"$sm->createTable('xf_gram_support_event', function($table) {","context":" $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);"},{"line":68,"text":"$sm->createTable('xf_gram_support_attachment_meta', function($table) {","context":" });\\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);"},{"line":78,"text":"$sm->createTable('xf_gram_support_delivery', function($table) {","context":" $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);"},{"line":94,"text":"$sm->createTable('xf_gram_support_rate_limit', function($table) {","context":" $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);"},{"line":104,"text":"public function uninstallStep1(): void","context":" }\\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) {"},{"line":106,"text":"$sm = $this->schemaManager();","context":" 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 }"},{"line":108,"text":"$sm->dropTable($name);","context":" $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}"}],"templates":{"gram_support.less":{"version_id":"1000100","version_string":"1.0.0 Alpha 3 Unified Fix 8","content":".gramSupport-launcher\n{\n\tposition: fixed;\n\tright: 18px;\n\tbottom: 18px;\n\tz-index: 500;\n\tborder-radius: 999px;\n\tbox-shadow: 0 6px 24px rgba(0, 0, 0, .22);\n}\n\n.gramSupport-messageMeta\n{\n\tfont-size: 12px;\n\topacity: .7;\n\tmargin-bottom: 6px;\n}\n\n.gramSupport-message--internal\n{\n\tborder-left: 4px solid currentColor;\n\topacity: .9;\n}\n\n@media (max-width: 650px)\n{\n\t.gramSupport-launcher\n\t{\n\t\tright: 12px;\n\t\tbottom: 12px;\n\t\tmax-width: calc(100vw - 24px);\n\t}\n}\n\n.gramSupport-messageBody\n{\n\twhite-space: pre-wrap;\n\toverflow-wrap: anywhere;\n}\n\n/* gram-support-footer-center-v1 */\n.gramSupport-launcher\n{\n position: static;\n inset: auto;\n z-index: auto;\n flex: 1 1 auto;\n display: flex;\n justify-content: center;\n align-items: center;\n width: auto;\n max-width: none;\n padding: 5px 18px;\n}\n\n.gramSupport-launcher .button.button--primary\n{\n position: relative;\n overflow: hidden;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 220px;\n min-height: 52px;\n padding: 11px 24px;\n border: 1px solid rgba(255, 213, 122, .78);\n border-radius: 14px;\n color: #fff1c4;\n background-image:\n linear-gradient(110deg, transparent 0%, transparent 43%, rgba(255, 255, 255, .42) 50%, transparent 57%, transparent 100%),\n linear-gradient(135deg, #533100 0%, #9a6208 24%, #d8a63a 48%, #a76d0b 70%, #4a2b00 100%);\n background-size: 260% 100%, 100% 100%;\n background-position: 180% 0, 0 0;\n box-shadow: inset 0 0 0 1px rgba(255, 246, 210, .12), 0 0 22px rgba(220, 166, 49, .38), 0 9px 26px rgba(0, 0, 0, .30);\n text-shadow: 0 1px 1px rgba(0, 0, 0, .45);\n animation: gramSupportFooterShimmer 4.8s ease-in-out infinite;\n transition: transform .18s ease, box-shadow .18s ease, filter .18s ease;\n}\n\n.gramSupport-launcher .button.button--primary:hover,\n.gramSupport-launcher .button.button--primary:focus-visible\n{\n filter: brightness(1.10) saturate(1.08);\n transform: translateY(-1px);\n box-shadow: inset 0 0 0 1px rgba(255, 249, 224, .20), 0 0 28px rgba(235, 184, 67, .50), 0 11px 30px rgba(0, 0, 0, .34);\n}\n\n.gramSupport-launcher .button-text\n{\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 10px;\n font-size: 17px;\n font-weight: 600;\n letter-spacing: .01em;\n}\n\n.gramSupport-launcher .button-text::before\n{\n content: \"\";\n flex: 0 0 auto;\n width: 20px;\n height: 16px;\n box-sizing: border-box;\n border: 2px solid currentColor;\n border-bottom: 0;\n border-radius: 12px 12px 0 0;\n}\n\n.gramSupport-launcher .button-text::after\n{\n content: \"\";\n position: absolute;\n left: 0;\n top: 50%;\n width: 4px;\n height: 8px;\n border-radius: 3px;\n background: currentColor;\n box-shadow: 16px 0 0 currentColor;\n transform: translateY(-5%);\n}\n\n@keyframes gramSupportFooterShimmer\n{\n 0%, 56% { background-position: 180% 0, 0 0; }\n 82%, 100% { background-position: -80% 0, 0 0; }\n}\n\n@media (max-width: 650px)\n{\n .p-footer-row\n {\n flex-wrap: wrap;\n }\n\n .gramSupport-launcher\n {\n order: 3;\n flex: 0 0 100%;\n width: 100%;\n max-width: none;\n padding: 10px 0 2px;\n }\n\n .gramSupport-launcher .button.button--primary\n {\n width: calc(100% - 32px);\n max-width: 320px;\n }\n}\n\n@media (prefers-reduced-motion: reduce)\n{\n .gramSupport-launcher .button.button--primary\n {\n animation: none;\n transition: none;\n }\n}\n\n/* gram-support-footer-align-v2 */\n@media (min-width: 901px)\n{\n .p-footer-row\n {\n position: relative;\n min-height: 64px;\n }\n\n .gramSupport-launcher\n {\n position: absolute;\n left: 50%;\n top: 50%;\n right: auto;\n bottom: auto;\n inset: auto;\n transform: translate(-50%, -50%);\n flex: 0 0 auto;\n width: auto;\n max-width: none;\n padding: 0;\n margin: 0;\n z-index: 2;\n }\n}\n\n@media (max-width: 900px)\n{\n .p-footer-row\n {\n flex-wrap: wrap;\n }\n\n .gramSupport-launcher\n {\n position: static;\n inset: auto;\n transform: none;\n order: 3;\n flex: 0 0 100%;\n width: 100%;\n max-width: none;\n padding: 10px 0 2px;\n margin: 0;\n z-index: auto;\n }\n\n .gramSupport-launcher .button.button--primary\n {\n width: calc(100% - 32px);\n max-width: 320px;\n }\n}\n\n/* gram-support-footer-align-v3-mobile-center */\n@media (max-width: 900px)\n{\n .gramSupport-launcher\n {\n display: flex;\n justify-content: center;\n align-items: center;\n text-align: center;\n }\n\n .gramSupport-launcher .button.button--primary\n {\n margin-left: auto;\n margin-right: auto;\n }\n}\n\n/* gram-support-footer-align-v4-desktop-inset */\n@media (min-width: 901px)\n{\n .gramSupport-launcher\n {\n inset: 50% auto auto 50%;\n transform: translate(-50%, -50%);\n }\n}\n\n/* gram-support-footer-align-v5-gap-grid */\n@media (min-width: 901px)\n{\n .p-footer-row\n {\n display: grid;\n grid-template-columns: max-content minmax(0, 1fr) max-content;\n align-items: center;\n column-gap: 16px;\n }\n\n .p-footer-row-main\n {\n grid-column: 1;\n min-width: 0;\n }\n\n .p-footer-row > .gramSupport-launcher\n {\n grid-column: 2;\n grid-row: 1;\n position: static;\n inset: auto;\n transform: none;\n width: auto;\n margin: 0;\n justify-self: center;\n align-self: center;\n }\n\n .p-footer-row-opposite\n {\n grid-column: 3;\n min-width: 0;\n justify-self: end;\n }\n}\n\n/* gram-support-footer-align-v6-gap-grid-force */\n@keyframes gramSupportFooterShimmerV6\n{\n 0% { background-position: 0% 50%; }\n 100% { background-position: 200% 50%; }\n}\n\nhtml body .p-footer .p-footer-row\n{\n position: relative !important;\n}\n\nhtml body .p-footer .p-footer-row > .gramSupport-launcher.button\n{\n display: inline-flex !important;\n align-items: center !important;\n justify-content: center !important;\n gap: .45em !important;\n box-sizing: border-box !important;\n min-height: 38px !important;\n max-width: 100% !important;\n padding: 8px 16px !important;\n border: 1px solid rgba(255, 225, 128, .88) !important;\n border-radius: 999px !important;\n color: #241700 !important;\n background: linear-gradient(120deg, #7c4b00 0%, #c88a16 18%, #f0c85a 36%, #fff1a8 50%, #d9a52f 66%, #8a5404 84%, #c88a16 100%) !important;\n background-size: 220% 100% !important;\n box-shadow: 0 0 14px rgba(235, 176, 44, .42), 0 0 28px rgba(235, 176, 44, .16), inset 0 1px 0 rgba(255, 255, 255, .45) !important;\n font-weight: 700 !important;\n line-height: 1.2 !important;\n text-decoration: none !important;\n white-space: nowrap !important;\n animation: gramSupportFooterShimmerV6 3.2s linear infinite !important;\n}\n\nhtml body .p-footer .p-footer-row > .gramSupport-launcher.button::before\n{\n content: \" \" !important;\n display: inline-block !important;\n flex: 0 0 16px !important;\n width: 16px !important;\n height: 14px !important;\n box-sizing: border-box !important;\n margin-right: .10em !important;\n color: #2b1a00 !important;\n border: 2px solid currentColor !important;\n border-bottom: 0 !important;\n border-radius: 9px 9px 2px 2px !important;\n background:\n linear-gradient(currentColor, currentColor) left bottom / 3px 6px no-repeat,\n linear-gradient(currentColor, currentColor) right bottom / 3px 6px no-repeat !important;\n}\n\n@media (min-width: 901px)\n{\n html body .p-footer .p-footer-row\n {\n display: grid !important;\n grid-template-columns: max-content minmax(0, 1fr) max-content !important;\n align-items: center !important;\n column-gap: 16px !important;\n }\n\n html body .p-footer .p-footer-row-main\n {\n grid-column: 1 !important;\n grid-row: 1 !important;\n float: none !important;\n min-width: 0 !important;\n margin-left: 0 !important;\n margin-right: 0 !important;\n }\n\n html body .p-footer .p-footer-row-opposite\n {\n grid-column: 3 !important;\n grid-row: 1 !important;\n float: none !important;\n min-width: 0 !important;\n margin-left: 0 !important;\n margin-right: 0 !important;\n justify-self: end !important;\n }\n\n html body .p-footer .p-footer-row > .gramSupport-launcher.button\n {\n grid-column: 2 !important;\n grid-row: 1 !important;\n position: static !important;\n inset: auto !important;\n top: auto !important;\n right: auto !important;\n bottom: auto !important;\n left: auto !important;\n transform: none !important;\n width: max-content !important;\n margin: 0 !important;\n float: none !important;\n justify-self: center !important;\n align-self: center !important;\n }\n}\n\n@media (max-width: 900px)\n{\n html body .p-footer .p-footer-row\n {\n display: grid !important;\n grid-template-columns: minmax(0, 1fr) !important;\n align-items: center !important;\n row-gap: 8px !important;\n }\n\n html body .p-footer .p-footer-row-main\n {\n grid-column: 1 !important;\n grid-row: 1 !important;\n float: none !important;\n min-width: 0 !important;\n margin-left: 0 !important;\n margin-right: 0 !important;\n justify-self: stretch !important;\n }\n\n html body .p-footer .p-footer-row-opposite\n {\n grid-column: 1 !important;\n grid-row: 2 !important;\n float: none !important;\n min-width: 0 !important;\n margin-left: 0 !important;\n margin-right: 0 !important;\n justify-self: stretch !important;\n }\n\n html body .p-footer .p-footer-row > .gramSupport-launcher.button\n {\n grid-column: 1 !important;\n grid-row: 3 !important;\n position: static !important;\n inset: auto !important;\n top: auto !important;\n right: auto !important;\n bottom: auto !important;\n left: auto !important;\n transform: none !important;\n width: max-content !important;\n margin: 4px 0 0 !important;\n float: none !important;\n justify-self: center !important;\n align-self: center !important;\n }\n}\n\n","sha256":"4482bdc4eadbbaa7cd515303a1a76500eb4be2dfeb1a4d0ebd41ea99b2465e17"},"gram_support_launcher":{"version_id":"1000050","version_string":"1.0.0 Alpha 3 Unified Fix 3","content":"\n\n\n\n\t\n\t\t{{ phrase('gram_support_open_support') }}\n\t\n\n","sha256":"eb8510732480507f86c2401a5d49c465820c225c9a3519530f751f6f501eaf5d"}},"codevipe":{"ok":true,"addon":null,"counts":{"xf_content_type_field":0,"xf_code_event_listener":0,"xf_option":0,"xf_option_group":0,"xf_permission":0,"xf_permission_interface_group":0,"xf_phrase":0,"xf_route":0,"xf_template":0,"xf_template_modification":0},"support_tables":["xf_gram_support_attachment_meta","xf_gram_support_delivery","xf_gram_support_event","xf_gram_support_message","xf_gram_support_rate_limit","xf_gram_support_ticket"],"support_table_rows":{"xf_gram_support_attachment_meta":0,"xf_gram_support_delivery":0,"xf_gram_support_event":0,"xf_gram_support_message":0,"xf_gram_support_rate_limit":0,"xf_gram_support_ticket":0},"routes":[],"jobs":[{"job_id":4,"execute_class":"XF\\Job\\Cron","manual_execute":0},{"job_id":50,"execute_class":"XF\\Job\\UpgradeCheck","manual_execute":0}],"error_max":0,"recent_errors":[],"schema_manager_createTable":{"ok":true,"class":"XF\\Db\\SchemaManager","parameters":[{"name":"tableName","optional":false},{"name":"toApply","optional":false}],"file_basename":"SchemaManager.php","start":187,"end":200,"source_sha256":"be6c143b9b8321148d841530fe0e5f8388b5fa178a96a8a1fe759e8208eb71a4","key_lines":[{"line":187,"text":"public function createTable($tableName, \\Closure $toApply)"},{"line":189,"text":"$create = $this->newTable($tableName);"},{"line":193,"text":"$toApply($create);"},{"line":194,"text":"$create->apply();"},{"line":198,"text":"$this->handleException($e, $tableName, $create);"}]},"board_active":"1","board_url":"https://codevipe.ru"},"assessment":{"expected_partial_state":true,"support_tables_all_empty":true,"schema_createTable_truthy_optional_default":false,"schema_createTable_exists_signal":false,"setup_createTable_hits":6,"setup_dropTable_hits":1,"retry_without_delete_candidate":false},"requested_footer_patch":{"goal":"center button in remaining gap between left footer block and right footer links; vertical center aligned with footer text","css_override":".p-footer-row {\n align-items: center;\n}\n.gramSupport-launcher {\n position: static;\n flex: 1 1 auto;\n min-width: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n align-self: center;\n margin: 0 16px;\n}\n.gramSupport-launcher .button {\n margin: 0;\n}","strategy":"launcher already inserted immediately before p-footer-row-opposite; make launcher flex-grow and center contents"}} -GRAM513R3R2_DECISION=PASS_PARTIAL_STATE_INSTALLABILITY_RCA -GRAM513R3R2_NEXT_GATE=HOLD_REQUIRES_INSTALL_PATH_DECISION_NO_DELETE -HOMELAB_RESULT_CONTRACT={"version":1,"command_id":"SUPPORT-260918-GRAM-XF-CODEVIPE-PARTIAL-STATE-INSTALLABILITY-RCA-513R3R2","status":"OK","changes_made":false,"rollback_started":false,"rollback_restored":null} +GRAM513R3R3_SAFE_REPORT={"artifact":{"sha256":"2e31f89d3626a83c1211910aa6fd279cc04689b75ba822899952865085cf551e","version_id":1000120,"version_string":"1.0.0 Alpha 3 Unified Fix 10","setup_tables":["xf_gram_support_ticket","xf_gram_support_message","xf_gram_support_event","xf_gram_support_attachment_meta","xf_gram_support_delivery","xf_gram_support_rate_limit"],"setup_sha256":"4977f90ec0444e2e3a1e4ee9b79a4e88098c5a3ae37b30d63e77cff2e1fcb971"},"codevipe":{"ok":true,"tables":{"xf_gram_support_ticket":{"exists":true,"rows":0,"ddl_sha256":"3558077fc70b4453960d1d782998ad498b2d3b12ba587488e8b23785979f7ba8","ddl":"CREATE TABLE `xf_gram_support_ticket` (\n `ticket_id` int(10) unsigned NOT NULL AUTO_INCREMENT,\n `public_ref` varchar(64) NOT NULL,\n `site_id` varchar(32) NOT NULL,\n `user_id` int(10) unsigned NOT NULL DEFAULT 0,\n `guest_email` varchar(255) NOT NULL DEFAULT '',\n `guest_access_token_hash` char(64) NOT NULL DEFAULT '',\n `guest_access_expires` int(10) unsigned NOT NULL DEFAULT 0,\n `node_id` int(10) unsigned NOT NULL DEFAULT 0,\n `thread_id` int(10) unsigned NOT NULL DEFAULT 0,\n `post_id` int(10) unsigned NOT NULL DEFAULT 0,\n `category` varchar(64) NOT NULL DEFAULT '',\n `subject` varchar(255) NOT NULL DEFAULT '',\n `status` varchar(32) NOT NULL DEFAULT 'NEW',\n `assigned_user_id` int(10) unsigned NOT NULL DEFAULT 0,\n `created_date` int(10) unsigned NOT NULL DEFAULT 0,\n `updated_date` int(10) unsigned NOT NULL DEFAULT 0,\n `resolved_date` int(10) unsigned NOT NULL DEFAULT 0,\n `context_json` mediumtext NOT NULL,\n `last_message_id` int(10) unsigned NOT NULL DEFAULT 0,\n PRIMARY KEY (`ticket_id`),\n UNIQUE KEY `public_ref` (`public_ref`),\n KEY `guest_token_hash` (`guest_access_token_hash`),\n KEY `site_user_updated` (`site_id`,`user_id`,`updated_date`),\n KEY `site_status_updated` (`site_id`,`status`,`updated_date`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci"},"xf_gram_support_message":{"exists":true,"rows":0,"ddl_sha256":"a00e534c642179db3018c74060d1aa6cef4dc445dcb801eb847c04d770f8f884","ddl":"CREATE TABLE `xf_gram_support_message` (\n `message_id` int(10) unsigned NOT NULL AUTO_INCREMENT,\n `ticket_id` int(10) unsigned NOT NULL,\n `user_id` int(10) unsigned NOT NULL DEFAULT 0,\n `is_staff` tinyint(3) unsigned NOT NULL DEFAULT 0,\n `is_internal` tinyint(3) unsigned NOT NULL DEFAULT 0,\n `message` mediumtext NOT NULL,\n `message_date` int(10) unsigned NOT NULL DEFAULT 0,\n PRIMARY KEY (`message_id`),\n KEY `ticket_date` (`ticket_id`,`message_date`),\n KEY `ticket_public_date` (`ticket_id`,`is_internal`,`message_date`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci"},"xf_gram_support_event":{"exists":true,"rows":0,"ddl_sha256":"81b6328dbbcf3f6405891897ba185e29890c675f21d7a2f9caf827c0eddb42da","ddl":"CREATE TABLE `xf_gram_support_event` (\n `event_id` int(10) unsigned NOT NULL AUTO_INCREMENT,\n `ticket_id` int(10) unsigned NOT NULL,\n `site_id` varchar(32) NOT NULL,\n `actor_user_id` int(10) unsigned NOT NULL DEFAULT 0,\n `event_type` varchar(64) NOT NULL,\n `event_date` int(10) unsigned NOT NULL DEFAULT 0,\n `safe_payload_json` mediumtext NOT NULL,\n PRIMARY KEY (`event_id`),\n KEY `ticket_date` (`ticket_id`,`event_date`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci"},"xf_gram_support_attachment_meta":{"exists":true,"rows":0,"ddl_sha256":"3c3d2ce4c5dae793687243dca37f60cd781895818b546a68e227aef9bfc9b6b2","ddl":"CREATE TABLE `xf_gram_support_attachment_meta` (\n `attachment_id` int(10) unsigned NOT NULL,\n `ticket_id` int(10) unsigned NOT NULL,\n `message_id` int(10) unsigned NOT NULL DEFAULT 0,\n `is_internal` tinyint(3) unsigned NOT NULL DEFAULT 0,\n `created_date` int(10) unsigned NOT NULL DEFAULT 0,\n PRIMARY KEY (`attachment_id`),\n KEY `ticket_internal` (`ticket_id`,`is_internal`),\n KEY `message_id` (`message_id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci"},"xf_gram_support_delivery":{"exists":true,"rows":0,"ddl_sha256":"91f068994bdbe4b168ab1c82fa669180f13825e6d1a7f5b9e956ccc872d0410d","ddl":"CREATE TABLE `xf_gram_support_delivery` (\n `delivery_key` char(64) NOT NULL,\n `event_id` int(10) unsigned NOT NULL,\n `consumer` varchar(32) NOT NULL,\n `recipient_key` varchar(96) NOT NULL,\n `state` varchar(16) NOT NULL DEFAULT 'pending',\n `lease_expires` int(10) unsigned NOT NULL DEFAULT 0,\n `attempt_count` int(10) unsigned NOT NULL DEFAULT 0,\n `last_failure_class` varchar(191) NOT NULL DEFAULT '',\n `created_date` int(10) unsigned NOT NULL DEFAULT 0,\n `updated_date` int(10) unsigned NOT NULL DEFAULT 0,\n `sent_date` int(10) unsigned NOT NULL DEFAULT 0,\n PRIMARY KEY (`delivery_key`),\n KEY `event_consumer` (`event_id`,`consumer`),\n KEY `state_lease` (`state`,`lease_expires`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci"},"xf_gram_support_rate_limit":{"exists":true,"rows":0,"ddl_sha256":"f2271e20d520a8ba413b2094a4f8f6640395065c7d9c2e4f5b0a74b790d3dd8e","ddl":"CREATE TABLE `xf_gram_support_rate_limit` (\n `rate_key` char(64) NOT NULL,\n `window_start` int(10) unsigned NOT NULL,\n `hit_count` int(10) unsigned NOT NULL DEFAULT 0,\n `updated_date` int(10) unsigned NOT NULL DEFAULT 0,\n PRIMARY KEY (`rate_key`),\n KEY `updated_date` (`updated_date`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci"}},"addon":null,"schema_manager_class":"XF\\Db\\SchemaManager","schema_methods":{"createTable":{"ok":true,"class":"XF\\Db\\SchemaManager","method":"createTable","file":"SchemaManager.php","start":187,"end":200,"sha256":"be6c143b9b8321148d841530fe0e5f8388b5fa178a96a8a1fe759e8208eb71a4","source":"\tpublic function createTable($tableName, \\Closure $toApply)\n\t{\n\t\t$create = $this->newTable($tableName);\n\n\t\ttry\n\t\t{\n\t\t\t$toApply($create);\n\t\t\t$create->apply();\n\t\t}\n\t\tcatch (\\Exception $e)\n\t\t{\n\t\t\t$this->handleException($e, $tableName, $create);\n\t\t}\n\t}\n","lines":[{"line":187,"text":"\tpublic function createTable($tableName, \\Closure $toApply)"},{"line":188,"text":"\t{"},{"line":189,"text":"\t\t$create = $this->newTable($tableName);"},{"line":190,"text":""},{"line":191,"text":"\t\ttry"},{"line":192,"text":"\t\t{"},{"line":193,"text":"\t\t\t$toApply($create);"},{"line":194,"text":"\t\t\t$create->apply();"},{"line":195,"text":"\t\t}"},{"line":196,"text":"\t\tcatch (\\Exception $e)"},{"line":197,"text":"\t\t{"},{"line":198,"text":"\t\t\t$this->handleException($e, $tableName, $create);"},{"line":199,"text":"\t\t}"},{"line":200,"text":"\t}"}]},"newTable":{"ok":true,"class":"XF\\Db\\SchemaManager","method":"newTable","file":"SchemaManager.php","start":239,"end":242,"sha256":"482ad432f7e1304bb4289a1e56fb600d7dfb3708393ec2fd4d6ceba61f8d61de","source":"\tpublic function newTable($tableName)\n\t{\n\t\treturn new Create($this->db, $this, $tableName);\n\t}\n","lines":[{"line":239,"text":"\tpublic function newTable($tableName)"},{"line":240,"text":"\t{"},{"line":241,"text":"\t\treturn new Create($this->db, $this, $tableName);"},{"line":242,"text":"\t}"}]},"handleException":{"ok":true,"class":"XF\\Db\\SchemaManager","method":"handleException","file":"SchemaManager.php","start":254,"end":270,"sha256":"bcfbb554306aeb3c108d447c45183c8d6c2415d91e9e785a9671ea1900dbc103","source":"\tprotected function handleException($exception, $tableName, AbstractDdl $ddl)\n\t{\n\t\t// The exception might have some extra useful stuff in it, so include attempt to modify the message directly.\n\n\t\ttry\n\t\t{\n\t\t\t$reflectionClass = new \\ReflectionClass($exception);\n\t\t\t$messageProperty = $reflectionClass->getProperty('message');\n\t\t\t$messageProperty->setAccessible(true);\n\t\t\t$messageProperty->setValue($exception, $tableName . ': ' . $messageProperty->getValue($exception));\n\t\t}\n\t\tcatch (\\ReflectionException $ignored)\n\t\t{\n\t\t}\n\n\t\tthrow $exception;\n\t}\n","lines":[{"line":254,"text":"\tprotected function handleException($exception, $tableName, AbstractDdl $ddl)"},{"line":255,"text":"\t{"},{"line":256,"text":"\t\t// The exception might have some extra useful stuff in it, so include attempt to modify the message directly."},{"line":257,"text":""},{"line":258,"text":"\t\ttry"},{"line":259,"text":"\t\t{"},{"line":260,"text":"\t\t\t$reflectionClass = new \\ReflectionClass($exception);"},{"line":261,"text":"\t\t\t$messageProperty = $reflectionClass->getProperty('message');"},{"line":262,"text":"\t\t\t$messageProperty->setAccessible(true);"},{"line":263,"text":"\t\t\t$messageProperty->setValue($exception, $tableName . ': ' . $messageProperty->getValue($exception));"},{"line":264,"text":"\t\t}"},{"line":265,"text":"\t\tcatch (\\ReflectionException $ignored)"},{"line":266,"text":"\t\t{"},{"line":267,"text":"\t\t}"},{"line":268,"text":""},{"line":269,"text":"\t\tthrow $exception;"},{"line":270,"text":"\t}"}]},"alterTable":{"ok":true,"class":"XF\\Db\\SchemaManager","method":"alterTable","file":"SchemaManager.php","start":150,"end":163,"sha256":"5e9788e5e9344db7c332d6c7e728a050f83967ac6d9d8a06727d266dcbbcc787","source":"\tpublic function alterTable($tableName, \\Closure $toApply)\n\t{\n\t\t$alter = $this->newAlter($tableName);\n\n\t\ttry\n\t\t{\n\t\t\t$toApply($alter);\n\t\t\t$alter->apply();\n\t\t}\n\t\tcatch (\\Exception $e)\n\t\t{\n\t\t\t$this->handleException($e, $tableName, $alter);\n\t\t}\n\t}\n","lines":[{"line":150,"text":"\tpublic function alterTable($tableName, \\Closure $toApply)"},{"line":151,"text":"\t{"},{"line":152,"text":"\t\t$alter = $this->newAlter($tableName);"},{"line":153,"text":""},{"line":154,"text":"\t\ttry"},{"line":155,"text":"\t\t{"},{"line":156,"text":"\t\t\t$toApply($alter);"},{"line":157,"text":"\t\t\t$alter->apply();"},{"line":158,"text":"\t\t}"},{"line":159,"text":"\t\tcatch (\\Exception $e)"},{"line":160,"text":"\t\t{"},{"line":161,"text":"\t\t\t$this->handleException($e, $tableName, $alter);"},{"line":162,"text":"\t\t}"},{"line":163,"text":"\t}"}]},"renameTable":{"ok":true,"class":"XF\\Db\\SchemaManager","method":"renameTable","file":"SchemaManager.php","start":169,"end":181,"sha256":"c352def9c86f9233a9c629670c5334a436092765a9c121807a21ef536510d7db","source":"\tpublic function renameTable($oldTableName, $newTableName)\n\t{\n\t\t$alter = $this->newAlter($oldTableName)->renameTo($newTableName);\n\n\t\ttry\n\t\t{\n\t\t\t$alter->apply();\n\t\t}\n\t\tcatch (\\Exception $e)\n\t\t{\n\t\t\t$this->handleException($e, $oldTableName, $alter);\n\t\t}\n\t}\n","lines":[{"line":169,"text":"\tpublic function renameTable($oldTableName, $newTableName)"},{"line":170,"text":"\t{"},{"line":171,"text":"\t\t$alter = $this->newAlter($oldTableName)->renameTo($newTableName);"},{"line":172,"text":""},{"line":173,"text":"\t\ttry"},{"line":174,"text":"\t\t{"},{"line":175,"text":"\t\t\t$alter->apply();"},{"line":176,"text":"\t\t}"},{"line":177,"text":"\t\tcatch (\\Exception $e)"},{"line":178,"text":"\t\t{"},{"line":179,"text":"\t\t\t$this->handleException($e, $oldTableName, $alter);"},{"line":180,"text":"\t\t}"},{"line":181,"text":"\t}"}]},"tableExists":{"ok":true,"class":"XF\\Db\\SchemaManager","method":"tableExists","file":"SchemaManager.php","start":119,"end":124,"sha256":"234d0c64067ebbf246972acbed6d58574c535e2ad78478d529afd97963551070","source":"\tpublic function tableExists($tableName)\n\t{\n\t\t$status = $this->getTableStatus($tableName);\n\n\t\treturn $status ? true : false;\n\t}\n","lines":[{"line":119,"text":"\tpublic function tableExists($tableName)"},{"line":120,"text":"\t{"},{"line":121,"text":"\t\t$status = $this->getTableStatus($tableName);"},{"line":122,"text":""},{"line":123,"text":"\t\treturn $status ? true : false;"},{"line":124,"text":"\t}"}]}},"table_create_class":"XF\\Db\\Schema\\Create","table_create_methods":{"apply":{"ok":true,"class":"XF\\Db\\Schema\\Create","method":"apply","file":"AbstractDdl.php","start":152,"end":162,"sha256":"70bf8158872ac741e410f19c8a3893809f6a4514907495ec2fe6af5204446493","source":"\tpublic function apply()\n\t{\n\t\t$queries = $this->getQueries();\n\n\t\tforeach ($queries AS $query)\n\t\t{\n\t\t\t$this->db->query($query);\n\t\t}\n\n\t\treturn $queries;\n\t}\n","lines":[{"line":152,"text":"\tpublic function apply()"},{"line":153,"text":"\t{"},{"line":154,"text":"\t\t$queries = $this->getQueries();"},{"line":155,"text":""},{"line":156,"text":"\t\tforeach ($queries AS $query)"},{"line":157,"text":"\t\t{"},{"line":158,"text":"\t\t\t$this->db->query($query);"},{"line":159,"text":"\t\t}"},{"line":160,"text":""},{"line":161,"text":"\t\treturn $queries;"},{"line":162,"text":"\t}"}]},"getQueries":{"ok":true,"class":"XF\\Db\\Schema\\Create","method":"getQueries","file":"Create.php","start":26,"end":110,"sha256":"86696c181f223784f11bf6591fd070796b316648462933706f2702ca20eff475","source":"\tpublic function getQueries()\n\t{\n\t\t$tableName = $this->tableName;\n\n\t\t$queries = [];\n\n\t\t$query = 'CREATE TABLE';\n\n\t\tif ($this->checkExists)\n\t\t{\n\t\t\t$query .= ' IF NOT EXISTS';\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$existing = $this->db->getSchemaManager()->getTableStatus($tableName);\n\t\t\tif ($existing)\n\t\t\t{\n\t\t\t\t$existing = new static($this->db, $this->sm, $tableName);\n\t\t\t\t$existing->setDefinition();\n\n\t\t\t\tif ($this->compare($existing))\n\t\t\t\t{\n\t\t\t\t\t// new table is identical, so just skip it\n\t\t\t\t\treturn [];\n\t\t\t\t}\n\t\t\t\telse if ($this->forceChanges)\n\t\t\t\t{\n\t\t\t\t\t$conflictName = $tableName . '__conflict';\n\t\t\t\t\tif ($this->sm->tableExists($conflictName))\n\t\t\t\t\t{\n\t\t\t\t\t\t$i = 2;\n\t\t\t\t\t\twhile ($this->sm->tableExists($conflictName . $i))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$i++;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t$conflictName .= $i;\n\t\t\t\t\t}\n\t\t\t\t\t$queries[] = \"ALTER TABLE `$tableName` RENAME TO `$conflictName`\";\n\n\t\t\t\t\t$errorMessage = sprintf(\n\t\t\t\t\t\t\"Renamed table %s to %s to avoid schema conflict\",\n\t\t\t\t\t\t$tableName,\n\t\t\t\t\t\t$conflictName\n\t\t\t\t\t);\n\n\t\t\t\t\t\\XF::logError($errorMessage, true);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tthrow new \\LogicException(\"$tableName already exists, but the structure does not match.\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t$query .= \" `$tableName` (\\n\\t\";\n\n\t\t$tableDefinition = [];\n\t\tforeach ($this->addColumns AS $column)\n\t\t{\n\t\t\t$tableDefinition[] = $column->getDefinition();\n\t\t}\n\t\tforeach ($this->addIndexes AS $index)\n\t\t{\n\t\t\t$tableDefinition[$index->getIndexName()] = $index->getDefinition();\n\t\t}\n\n\t\t$query .= implode(\",\\n\\t\", $tableDefinition);\n\t\t$query .= \"\\n)\";\n\t\t$query .= ' ' . $this->db->getSchemaManager()->getTableConfigSql($this->engine ?: null);\n\n\t\tif ($this->comment)\n\t\t{\n\t\t\t$query .= ' COMMENT=' . $this->db->quote($this->comment);\n\t\t}\n\n\t\tif ($this->autoIncrementIndex !== null)\n\t\t{\n\t\t\t$query .= ' AUTO_INCREMENT=' . $this->autoIncrementIndex;\n\t\t}\n\n\t\t$queries[] = $query;\n\n\t\treturn $queries;\n\t}\n","lines":[{"line":26,"text":"\tpublic function getQueries()"},{"line":27,"text":"\t{"},{"line":28,"text":"\t\t$tableName = $this->tableName;"},{"line":29,"text":""},{"line":30,"text":"\t\t$queries = [];"},{"line":31,"text":""},{"line":32,"text":"\t\t$query = 'CREATE TABLE';"},{"line":33,"text":""},{"line":34,"text":"\t\tif ($this->checkExists)"},{"line":35,"text":"\t\t{"},{"line":36,"text":"\t\t\t$query .= ' IF NOT EXISTS';"},{"line":37,"text":"\t\t}"},{"line":38,"text":"\t\telse"},{"line":39,"text":"\t\t{"},{"line":40,"text":"\t\t\t$existing = $this->db->getSchemaManager()->getTableStatus($tableName);"},{"line":41,"text":"\t\t\tif ($existing)"},{"line":42,"text":"\t\t\t{"},{"line":43,"text":"\t\t\t\t$existing = new static($this->db, $this->sm, $tableName);"},{"line":44,"text":"\t\t\t\t$existing->setDefinition();"},{"line":45,"text":""},{"line":46,"text":"\t\t\t\tif ($this->compare($existing))"},{"line":47,"text":"\t\t\t\t{"},{"line":48,"text":"\t\t\t\t\t// new table is identical, so just skip it"},{"line":49,"text":"\t\t\t\t\treturn [];"},{"line":50,"text":"\t\t\t\t}"},{"line":51,"text":"\t\t\t\telse if ($this->forceChanges)"},{"line":52,"text":"\t\t\t\t{"},{"line":53,"text":"\t\t\t\t\t$conflictName = $tableName . '__conflict';"},{"line":54,"text":"\t\t\t\t\tif ($this->sm->tableExists($conflictName))"},{"line":55,"text":"\t\t\t\t\t{"},{"line":56,"text":"\t\t\t\t\t\t$i = 2;"},{"line":57,"text":"\t\t\t\t\t\twhile ($this->sm->tableExists($conflictName . $i))"},{"line":58,"text":"\t\t\t\t\t\t{"},{"line":59,"text":"\t\t\t\t\t\t\t$i++;"},{"line":60,"text":"\t\t\t\t\t\t}"},{"line":61,"text":""},{"line":62,"text":"\t\t\t\t\t\t$conflictName .= $i;"},{"line":63,"text":"\t\t\t\t\t}"},{"line":64,"text":"\t\t\t\t\t$queries[] = \"ALTER TABLE `$tableName` RENAME TO `$conflictName`\";"},{"line":65,"text":""},{"line":66,"text":"\t\t\t\t\t$errorMessage = sprintf("},{"line":67,"text":"\t\t\t\t\t\t\"Renamed table %s to %s to avoid schema conflict\","},{"line":68,"text":"\t\t\t\t\t\t$tableName,"},{"line":69,"text":"\t\t\t\t\t\t$conflictName"},{"line":70,"text":"\t\t\t\t\t);"},{"line":71,"text":""},{"line":72,"text":"\t\t\t\t\t\\XF::logError($errorMessage, true);"},{"line":73,"text":"\t\t\t\t}"},{"line":74,"text":"\t\t\t\telse"},{"line":75,"text":"\t\t\t\t{"},{"line":76,"text":"\t\t\t\t\tthrow new \\LogicException(\"$tableName already exists, but the structure does not match.\");"},{"line":77,"text":"\t\t\t\t}"},{"line":78,"text":"\t\t\t}"},{"line":79,"text":"\t\t}"},{"line":80,"text":""},{"line":81,"text":"\t\t$query .= \" `$tableName` (\\n\\t\";"},{"line":82,"text":""},{"line":83,"text":"\t\t$tableDefinition = [];"},{"line":84,"text":"\t\tforeach ($this->addColumns AS $column)"},{"line":85,"text":"\t\t{"},{"line":86,"text":"\t\t\t$tableDefinition[] = $column->getDefinition();"},{"line":87,"text":"\t\t}"},{"line":88,"text":"\t\tforeach ($this->addIndexes AS $index)"},{"line":89,"text":"\t\t{"},{"line":90,"text":"\t\t\t$tableDefinition[$index->getIndexName()] = $index->getDefinition();"},{"line":91,"text":"\t\t}"},{"line":92,"text":""},{"line":93,"text":"\t\t$query .= implode(\",\\n\\t\", $tableDefinition);"},{"line":94,"text":"\t\t$query .= \"\\n)\";"},{"line":95,"text":"\t\t$query .= ' ' . $this->db->getSchemaManager()->getTableConfigSql($this->engine ?: null);"},{"line":96,"text":""},{"line":97,"text":"\t\tif ($this->comment)"},{"line":98,"text":"\t\t{"},{"line":99,"text":"\t\t\t$query .= ' COMMENT=' . $this->db->quote($this->comment);"},{"line":100,"text":"\t\t}"},{"line":101,"text":""},{"line":102,"text":"\t\tif ($this->autoIncrementIndex !== null)"},{"line":103,"text":"\t\t{"},{"line":104,"text":"\t\t\t$query .= ' AUTO_INCREMENT=' . $this->autoIncrementIndex;"},{"line":105,"text":"\t\t}"},{"line":106,"text":""},{"line":107,"text":"\t\t$queries[] = $query;"},{"line":108,"text":""},{"line":109,"text":"\t\treturn $queries;"},{"line":110,"text":"\t}"}]},"getCreateQuery":{"ok":false,"class":"XF\\Db\\Schema\\Create","method":"getCreateQuery","error":"ReflectionException"},"exists":{"ok":false,"class":"XF\\Db\\Schema\\Create","method":"exists","error":"ReflectionException"}},"source_scans":[{"file":"src/XF/Cli/Command/AddOnActionTrait.php","sha256":"265c7bd3e5dbeb5669b52e57fc9c67411261be00e493cc717aa6b5c991421287","hits":[{"line":15,"text":"use XF\\AddOn\\StepResult;"},{"line":118,"text":"/** @var StepResult $result */"},{"line":131,"text":"$params['step'] = $result->step;"},{"line":219,"text":"'xf:addon-sub-action',"}]},{"file":"src/XF/Cli/Command/AddOnInstall.php","sha256":"2407ad9ae20ca8ac1ca84b456ac2adc537f39c79534da5e258167a4d0df2a54f","hits":[{"line":20,"text":"->setName('xf:addon-install')"}]},{"file":"src/XF/Cli/Command/AddOnList.php","sha256":"3047ffa03d4fa488cb8a53c2f0c8c88edd8372e5804340f72b3fd761b7eff1ea","hits":[{"line":136,"text":"'last_pending_action' => $installed->last_pending_action,"},{"line":198,"text":"$installed->last_pending_action ?: '-',"}]},{"file":"src/XF/Cli/Command/AddOnSubAction.php","sha256":"4cbf315edc17bf5773c624da2d1af076f47dd588398462d657f709d832adbb46","hits":[{"line":18,"text":"->setName('xf:addon-sub-action')"},{"line":19,"text":"->setDescription('Runs a add-on sub-action in a separate process. Do not run directly!')"},{"line":46,"text":"$output->writeln(\"Invalid sub-action confirmation key. Run from parent command.\");"}]},{"file":"src/XF/Cli/Command/Import.php","sha256":"cbc8b5707e84a1b1293ca00f57dcc91bb0ded0d3810eb976d0b93327c1dd32f5","hits":[{"line":14,"text":"use XF\\Import\\StepState;"},{"line":39,"text":"'If set, the import will be automatically finalized when the data import step completes.'"},{"line":112,"text":"function ($isComplete, $step, StepState $stepState, $importCompletion) use ($progressIndicator, &$progressStarted)"},{"line":114,"text":"$stepTitle = $stepState->title;"},{"line":115,"text":"if (!$stepTitle)"},{"line":132,"text":"$stepNumberStrlen = strlen((string) $importCompletion['total']);"},{"line":133,"text":"$stepNameStrlen = 25; // just arbitrary for now, but could be based on the strlen of the longest step title"},{"line":135,"text":"$stepInfo = sprintf("},{"line":136,"text":"\"Step %{$stepNumberStrlen}d of %d: %-{$stepNameStrlen}s \","},{"line":139,"text":"$stepTitle"},{"line":142,"text":"if ($stepState->complete)"},{"line":145,"text":"$stepInfo"},{"line":146,"text":". $this->getIntervalString($stepState->startDate, $stepState->completeDate)"},{"line":147,"text":". ' [' . \\XF::language()->numberFormat($stepState->imported) . ']'"},{"line":154,"text":"$stepInfo"},{"line":155,"text":". $this->getIntervalString($stepState->startDate, time()) . ' '"},{"line":156,"text":". $stepState->getCompletionOutput()"}]},{"file":"src/XF/Cli/Command/ImportChildProcess.php","sha256":"4018331a7104801b8d7c73c6bf90374e198ed576897a7b4b01e5195c9d5133f9","hits":[{"line":24,"text":"'step',"},{"line":26,"text":"'The name of the step to run.'"},{"line":63,"text":"$step = $input->getArgument('step');"},{"line":67,"text":"if (!$runner->validateChildProcessRun($step, $startAfter, $end, $error))"},{"line":78,"text":"$runner->runChildProcess($step, $startAfter, $end, $messageReceiver);"}]},{"file":"src/XF/Cli/Command/ImportCommandTrait.php","sha256":"a4816d99b66aa795a1558e01dc42169c471af78028e103533326ced8365f970b","hits":[{"line":21,"text":"$totalsTable->setHeaders(['Step', 'Total', 'Time taken']);"}]},{"file":"src/XF/Cli/Command/ImportFinalize.php","sha256":"78b8ed78256f621c461fe11a6b206a3871819c9960660029feb8d76134ecfde8","hits":[{"line":64,"text":"$jobs = $manager->getImporter($session->importerId)->getFinalizeJobs($session->getStepsRun());"}]},{"file":"src/XF/Cli/Command/Upgrade.php","sha256":"9f58a531299befbb84458add55bb9e701fc18cd06f49d5c86c15fd5871af1a61","hits":[{"line":70,"text":". ($lastUpgradeVersion['last_step'] ? \" (step $lastUpgradeVersion[last_step])\" : '')"},{"line":75,"text":"$upgradeComplete = ($lastUpgradeVersion['version_id'] === \\XF::$versionId && !$lastUpgradeVersion['last_step']);"},{"line":104,"text":"$step = 1;"},{"line":106,"text":"if ($lastUpgradeVersion['last_step'])"},{"line":109,"text":"$step = $lastUpgradeVersion['last_step'] + 1;"},{"line":115,"text":"$step = 1;"},{"line":126,"text":"$upgrader->assertValidUpgradeSteps($upgrade);"},{"line":132,"text":"while (method_exists($upgrade, 'step' . $step))"},{"line":136,"text":"$this->outputStatus($output, \"Running upgrade to $versionName, step $step ($position)...\");"},{"line":140,"text":"$this->outputStatus($output, \"Running upgrade to $versionName, step $step...\");"},{"line":143,"text":"$result = $upgrade->{'step' . $step}($position, $data, $controller);"},{"line":146,"text":"$this->clearStatus($output, 'This step must be completed via the web interface.');"},{"line":151,"text":"$this->clearStatus($output, \"Running upgrade to $versionName, step $step... done.\");"},{"line":156,"text":"$upgrader->insertUpgradeLog($runVersionId, $step);"},{"line":158,"text":"$this->clearStatus($output, \"Running upgrade to $versionName, step $step... done.\");"},{"line":160,"text":"$step++;"},{"line":166,"text":"// stay on the same step"},{"line":172,"text":"$this->clearStatus($output, 'The upgrade step returned an unexpected result.');"},{"line":180,"text":"$step = 1;"},{"line":184,"text":"$output->writeln(['All upgrade steps run up to version ' . \\XF::$version . '.', '']);"}]},{"file":"src/XF/Cli/Command/AddOn/AbstractSetupStep.php","sha256":"86ac6e9eda2202a75f3566a6bf20b14b5cc5171a823e0a23de0e66d0e8c0a8b7","hits":[{"line":9,"text":"use XF\\AddOn\\StepResult;"},{"line":16,"text":"abstract class AbstractSetupStep extends AbstractCommand"},{"line":21,"text":"abstract protected function getStepType();"},{"line":27,"text":"$command = $this->getStepType();"},{"line":30,"text":"->setName('xf-addon:' . $command . '-step')"},{"line":31,"text":"->setDescription('Runs a specific step from the specified add-on Setup class.')"},{"line":60,"text":"$step = $input->getArgument('step');"},{"line":64,"text":"$stepType = $this->getStepType();"},{"line":65,"text":"if ($stepType == 'upgrade')"},{"line":70,"text":"$setup->prepareForAction($stepType);"},{"line":74,"text":"$result = $this->runStep($setup, $output, $stepType, $step, $version, $params);"},{"line":75,"text":"if (!($result instanceof StepResult))"},{"line":77,"text":"$this->clearStatus($output, \"Must return a StepResult object.\");"},{"line":104,"text":"protected function runStep(AbstractSetup $setup, OutputInterface $output, $stepType, $step, $version = null, array $params = [])"},{"line":106,"text":"$method = $stepType;"},{"line":112,"text":"if ($step)"},{"line":114,"text":"$method .= 'Step' . $step;"},{"line":119,"text":"if ($version && $step)"},{"line":121,"text":"$method .= $version . 'Step' . $step;"},{"line":129,"text":"return new StepResult(true);"},{"line":137,"text":"$result = new StepResult(true);"},{"line":142,"text":"$result = new StepResult(false, $result);"}]},{"file":"src/XF/Cli/Command/AddOn/Create.php","sha256":"4ff8f77caa12327158b9a6ba6ed2ffe85b959011279be5a70a8b3e77f75204f5","hits":[{"line":217,"text":"$question = new ConfirmationQuestion(\"Does your Setup need to support running multiple steps? (y/n) \");"},{"line":226,"text":"use XF\\AddOn\\StepRunnerInstallTrait;"},{"line":227,"text":"use XF\\AddOn\\StepRunnerUninstallTrait;"},{"line":228,"text":"use XF\\AddOn\\StepRunnerUpgradeTrait;"},{"line":232,"text":"use StepRunnerInstallTrait;"},{"line":233,"text":"use StepRunnerUpgradeTrait;"},{"line":234,"text":"use StepRunnerUninstallTrait;"},{"line":250,"text":"public function install(array \\$stepParams = [])"},{"line":255,"text":"public function upgrade(array \\$stepParams = [])"},{"line":260,"text":"public function uninstall(array \\$stepParams = [])"},{"line":283,"text":"$output->writeln(\"If you change your mind, create a file named Setup.php in \" . dirname($setupPath) . \" which should extend AbstractSetup and optionally use one of the StepRunnerX traits.\");"}]},{"file":"src/XF/Cli/Command/AddOn/InstallStep.php","sha256":"5536a7cdaa190b8ddff16e58733a546c3735ae8e55ab4c9d3cf1e1acce615ca2","hits":[{"line":7,"text":"class InstallStep extends AbstractSetupStep"},{"line":9,"text":"protected function getStepType()"},{"line":17,"text":"'step',"},{"line":19,"text":"'The step number to run.'"}]},{"file":"src/XF/Cli/Command/AddOn/UninstallStep.php","sha256":"d69b287acd3ea5c02bf23492e1bdef465fb75f22f00b45acdb4ffafe547260e5","hits":[{"line":7,"text":"class UninstallStep extends AbstractSetupStep"},{"line":9,"text":"protected function getStepType()"},{"line":17,"text":"'step',"},{"line":19,"text":"'The step number to run.'"}]},{"file":"src/XF/Cli/Command/AddOn/UpgradeStep.php","sha256":"51d6bcea38a819ab7a983340112de1b9778ed9efeb0a139f8d0b6c967b4e052f","hits":[{"line":7,"text":"class UpgradeStep extends AbstractSetupStep"},{"line":9,"text":"protected function getStepType()"},{"line":23,"text":"'step',"},{"line":25,"text":"'The step number to run.'"}]},{"file":"src/XF/Cli/Command/Rebuild/AbstractRebuildCommand.php","sha256":"9b019518b8fb2d2e3bf6d281acb57e181c4b48f2acbf654efdc81b87f294c7f4","hits":[{"line":56,"text":"'resume',"},{"line":73,"text":"if ($input->getOption('resume'))"},{"line":81,"text":"$output->writeln(\"There are no pending jobs of this type to resume.\");"}]},{"file":"src/XF/Cli/Command/EmbedMetadata/AbstractEmbedMetadataCommand.php","sha256":"d58bdc8eb04615e12b7838403db010fb05ff9238203467061fd7f0bb2d6274f9","hits":[{"line":74,"text":"'resume',"},{"line":77,"text":"'Resume an existing pending job instead of starting a new one. Without this flag, re-running the command discards any prior progress and restarts from the beginning.'"},{"line":92,"text":"if ($input->getOption('resume'))"},{"line":100,"text":"$output->writeln(\"There are no pending jobs of this type to resume.\");"}]},{"file":"src/XF/Cli/Command/Development/UpgradeStep.php","sha256":"6c91e119b41e5d2b83da72f7d37c02ff2f3d6149b7b7974e05ab3539f0e59fd5","hits":[{"line":18,"text":"class UpgradeStep extends AbstractCommand implements CustomAppCommandInterface"},{"line":30,"text":"->setName('xf-dev:upgrade-step')"},{"line":31,"text":"->setDescription('Runs a specific upgrade step from a specified upgrade class.')"},{"line":38,"text":"'step',"},{"line":40,"text":"'The step number to run'"},{"line":54,"text":"$step = $input->getArgument('step');"},{"line":60,"text":"$returnCode = $this->runStep($upgrade, $output, $controller, $step, $position, $data);"},{"line":73,"text":"throw new \\LogicException(\"Step did not return an expected result\");"},{"line":81,"text":"protected function runStep(AbstractUpgrade $upgrade, OutputInterface $output, Upgrade $controller, $step, $position = 0, $data = [])"},{"line":85,"text":"if (!method_exists($upgrade, 'step' . $step))"},{"line":87,"text":"$this->clearStatus($output, \"Upgrade to version $versionName does not have a step$step() method.\");"},{"line":93,"text":"$this->outputStatus($output, \"Running upgrade to $versionName, step $step ($position)...\");"},{"line":97,"text":"$this->outputStatus($output, \"Running upgrade to $versionName, step $step...\");"},{"line":100,"text":"$result = $upgrade->{'step' . $step}($position, $data, $controller);"},{"line":103,"text":"$this->clearStatus($output, \"This step must be completed via the web interface.\");"},{"line":108,"text":"$this->clearStatus($output, \"Running upgrade to $versionName, step $step... done.\");"},{"line":113,"text":"// stay on the same step"},{"line":118,"text":"$this->clearStatus($output, \"The upgrade step returned an unexpected result.\");"}]},{"file":"src/XF/AddOn/AbstractSetup.php","sha256":"6bdd3fe834e15b963a52c9357f54262f2d12f3c7c3686fc31333b549cddf2d88","hits":[{"line":21,"text":"* @param array $stepParams"},{"line":23,"text":"* @return null|StepResult"},{"line":25,"text":"abstract public function install(array $stepParams = []);"},{"line":28,"text":"* @param array $stepParams"},{"line":30,"text":"* @return null|StepResult"},{"line":32,"text":"abstract public function upgrade(array $stepParams = []);"},{"line":35,"text":"* @param array $stepParams"},{"line":37,"text":"* @return null|StepResult"},{"line":39,"text":"abstract public function uninstall(array $stepParams = []);"}]},{"file":"src/XF/AddOn/AddOn.php","sha256":"0e0346a046fff6bde9850cb53e9dc0d0b5379387029dc16925e562fa141ab422","hits":[{"line":346,"text":"$lastAction = $this->installedAddOn->getLastActionStep('install');"},{"line":349,"text":"// we haven't completed the install steps yet, don't consider as installed"},{"line":537,"text":"public function updatePendingAction($action, $step)"},{"line":541,"text":"$this->installedAddOn->fastUpdate('last_pending_action', \"$action:$step\");"},{"line":549,"text":"$this->installedAddOn->fastUpdate('last_pending_action', null);"},{"line":568,"text":"'last_pending_action' => 'install:0',"},{"line":653,"text":"$installed->last_pending_action = 'uninstall:0';"}]},{"file":"src/XF/AddOn/StepResult.php","sha256":"d486646b6b20370f7c03f473468ecec93e7cea3ef45cca8d72d6fe9b2701f9be","hits":[{"line":5,"text":"class StepResult"},{"line":9,"text":"public $step;"},{"line":12,"text":"public function __construct($complete, array $params = [], $step = null, $version = null)"},{"line":16,"text":"$this->step = $step;"}]},{"file":"src/XF/AddOn/StepRunnerInstallTrait.php","sha256":"1f441b8a3101b97009ae04e62c04e79062a89f1e01a08ae9e07c5e629c76d5f2","hits":[{"line":10,"text":"trait StepRunnerInstallTrait"},{"line":13,"text":"* @param array $stepParams"},{"line":15,"text":"* @return null|StepResult"},{"line":17,"text":"public function install(array $stepParams = [])"},{"line":19,"text":"$stepParams = array_replace(["},{"line":20,"text":"'step' => 0,"},{"line":21,"text":"], $stepParams);"},{"line":23,"text":"$step = $stepParams['step'];"},{"line":24,"text":"if (!$step)"},{"line":26,"text":"$step = $this->getInstallResumeStep();"},{"line":29,"text":"return $this->installStepRunner($step, $stepParams);"},{"line":32,"text":"private function getInstallResumeStep()"},{"line":37,"text":"$lastActionStep = $installedAddOn->getLastActionStep('install');"},{"line":38,"text":"if ($lastActionStep)"},{"line":40,"text":"return $lastActionStep + 1; // this is the last completed step, so resume with the next"},{"line":48,"text":"* @param integer $step"},{"line":49,"text":"* @param array $stepParams"},{"line":51,"text":"* @return null|StepResult"},{"line":53,"text":"private function installStepRunner($step, array $stepParams)"},{"line":55,"text":"$fnPrefix = 'installStep';"},{"line":56,"text":"$fn = $fnPrefix . $step;"},{"line":62,"text":"$result = $this->$fn($stepParams);"},{"line":65,"text":"$result = new StepResult(true);"},{"line":69,"text":"$result = new StepResult(false, $result);"},{"line":72,"text":"if (!($result instanceof StepResult))"},{"line":74,"text":"throw new \\LogicException(\"Must return a StepResult object\");"},{"line":77,"text":"$result->step = $step;"},{"line":81,"text":"$this->addOn->updatePendingAction('install', $result->step);"},{"line":83,"text":"$nextStep = $step + 1;"},{"line":84,"text":"$nextFn = $fnPrefix . $nextStep;"},{"line":90,"text":"$result = new StepResult(false, [], $nextStep);"}]},{"file":"src/XF/AddOn/StepRunnerUninstallTrait.php","sha256":"e58a9ab9c30e3cf3c41a0be392e8c5ac37f744578f7b91f76d663139649c49a9","hits":[{"line":10,"text":"trait StepRunnerUninstallTrait"},{"line":13,"text":"* @param array $stepParams"},{"line":15,"text":"* @return null|StepResult"},{"line":17,"text":"public function uninstall(array $stepParams = [])"},{"line":19,"text":"$stepParams = array_replace(["},{"line":20,"text":"'step' => 0,"},{"line":21,"text":"], $stepParams);"},{"line":23,"text":"$step = $stepParams['step'];"},{"line":24,"text":"if (!$step)"},{"line":26,"text":"$step = $this->getUninstallResumeStep();"},{"line":28,"text":"return $this->uninstallStepRunner($step, $stepParams);"},{"line":31,"text":"private function getUninstallResumeStep()"},{"line":36,"text":"$lastActionStep = $installedAddOn->getLastActionStep('uninstall');"},{"line":37,"text":"if ($lastActionStep)"},{"line":39,"text":"return $lastActionStep + 1; // this is the last completed step, so resume with the next"},{"line":47,"text":"* @param integer $step"},{"line":48,"text":"* @param array $stepParams"},{"line":50,"text":"* @return null|StepResult"},{"line":52,"text":"private function uninstallStepRunner($step, array $stepParams)"},{"line":54,"text":"$fnPrefix = 'uninstallStep';"},{"line":55,"text":"$fn = $fnPrefix . $step;"},{"line":61,"text":"$result = $this->$fn($stepParams);"},{"line":64,"text":"$result = new StepResult(true);"},{"line":68,"text":"$result = new StepResult(false, $result);"},{"line":71,"text":"if (!($result instanceof StepResult))"},{"line":73,"text":"throw new \\LogicException(\"Must return a StepResult object\");"},{"line":76,"text":"$result->step = $step;"},{"line":80,"text":"$this->addOn->updatePendingAction('uninstall', $result->step);"},{"line":82,"text":"$nextStep = $step + 1;"},{"line":83,"text":"$nextFn = $fnPrefix . $nextStep;"},{"line":89,"text":"$result = new StepResult(false, [], $nextStep);"}]},{"file":"src/XF/AddOn/StepRunnerUpgradeTrait.php","sha256":"b61698d9c20f094cc1b704ad48798148fe5843e2dc746592cb2db252b579d1b5","hits":[{"line":10,"text":"trait StepRunnerUpgradeTrait"},{"line":13,"text":"* @param array $stepParams"},{"line":15,"text":"* @return null|StepResult"},{"line":17,"text":"public function upgrade(array $stepParams = [])"},{"line":19,"text":"$stepParams = $this->getStepParams($stepParams);"},{"line":22,"text":"$stepsGrouped = [];"},{"line":27,"text":"if (preg_match('/^upgrade(\\d+)Step(\\d+)$/', $method->name, $match))"},{"line":30,"text":"$step = intval($match[2]);"},{"line":33,"text":"$stepsGrouped[$versionId][$step] = $step;"},{"line":42,"text":"if (!$stepParams['version_id'])"},{"line":44,"text":"$resume = $this->getUpgradeResumeStep();"},{"line":45,"text":"$stepParams['version_id'] = $resume[0];"},{"line":46,"text":"$stepParams['step'] = $resume[1];"},{"line":49,"text":"$runStep = $stepParams['step'];"},{"line":50,"text":"if (!$runStep)"},{"line":52,"text":"$runStep = 1;"},{"line":60,"text":"if ($versionId >= $stepParams['version_id'])"},{"line":62,"text":"$versionSteps = $stepsGrouped[$versionId];"},{"line":63,"text":"if (isset($versionSteps[$runStep]))"},{"line":65,"text":"if ($versionId != $stepParams['version_id'] || $runStep != $stepParams['step'])"},{"line":67,"text":"// sanity check - don't pass params if we're changing versions or steps"},{"line":68,"text":"$stepParams = [];"},{"line":73,"text":"return $this->upgradeStepRunner($versionId, $runStep, $stepParams, $nextVersionId);"},{"line":76,"text":"// if we hit here, then the step couldn't be found, so move onto the next upgrade"},{"line":77,"text":"$runStep = 1;"},{"line":78,"text":"$stepParams = $this->getStepParams();"},{"line":86,"text":"protected function getStepParams(array $stepParams = [])"},{"line":90,"text":"'step' => 0,"},{"line":91,"text":"], $stepParams);"},{"line":94,"text":"private function getUpgradeResumeStep()"},{"line":97,"text":"$lastActionStep = $installedAddOn->getLastActionStep('upgrade');"},{"line":98,"text":"if ($lastActionStep)"},{"line":100,"text":"$lastActionStep[1]++; // we completed this step, so need to resume with the next"},{"line":101,"text":"return $lastActionStep;"},{"line":109,"text":"* @param integer $runStep"},{"line":110,"text":"* @param array $stepParams"},{"line":113,"text":"* @return null|StepResult"},{"line":115,"text":"private function upgradeStepRunner($runVersion, $runStep, array $stepParams, $nextVersionId)"},{"line":117,"text":"$fnPattern = 'upgrade%dStep%d';"},{"line":118,"text":"$fn = sprintf($fnPattern, $runVersion, $runStep);"},{"line":121,"text":"throw new \\LogicException(\"Step $fn doesn't exist. Should have been checked earlier.\");"},{"line":124,"text":"$result = $this->$fn($stepParams);"},{"line":127,"text":"$result = new StepResult(true);"},{"line":131,"text":"$result = new StepResult(false, $result);"},{"line":134,"text":"if (!($result instanceof StepResult))"},{"line":136,"text":"throw new \\LogicException(\"Must return a StepResult object\");"},{"line":139,"text":"$result->step = $runStep;"},{"line":144,"text":"$this->addOn->updatePendingAction('upgrade', $result->version . ':' . $result->step);"},{"line":146,"text":"$nextStep = $runStep + 1;"},{"line":147,"text":"$nextStepFn = sprintf($fnPattern, $runVersion, $nextStep);"},{"line":148,"text":"if (method_exists($this, $nextStepFn))"},{"line":150,"text":"$result = new StepResult(false, [], $nextStep, $runVersion);"},{"line":166,"text":"$result = new StepResult(false, [], 1, $nextVersionId);"}]},{"file":"src/XF/AddOn/DataType/AbstractDataType.php","sha256":"a4f6ec14e4009be0029548b07272dc77c6ad96f4cca4e067a7d3ea0004126815","hits":[{"line":165,"text":"protected function resume($maxRunTime, $startTime)"}]}]},"assessment":{"all_six_tables_present":true,"all_six_tables_empty":true,"duplicate_create_appears_safe":true,"native_resume_signal":true},"policy":{"delete_performed":false,"mutation_performed":false,"goal":"select a no-delete native or bounded bridge install path"}} +GRAM513R3R3_DECISION=PASS_NATIVE_RESUME_SCHEMA_RCA +GRAM513R3R3_NEXT_GATE=READY_FOR_DIRECT_NATIVE_RETRY_CANARY_513R3R4 +HOMELAB_RESULT_CONTRACT={"version":1,"command_id":"SUPPORT-260918-GRAM-XF-CODEVIPE-NATIVE-RESUME-SCHEMA-RCA-513R3R3","status":"OK","changes_made":false,"rollback_started":false,"rollback_restored":null} OUTPUT_END CHAT_OUTPUT_END