self::maxBytes()) { throw new ImportInvalid('too_large', __('The file is too large to import.', 'admin-options-pages'), [], 413); } // A byte order mark (some editors add one) is not part of the JSON. $content = preg_replace('/^\xEF\xBB\xBF/', '', $content); try { $data = json_decode($content, true, 32, JSON_THROW_ON_ERROR); } catch (\JsonException $exception) { throw new ImportInvalid('invalid_json', __('This is not a JSON file, or it is not valid UTF-8.', 'admin-options-pages')); } if (! is_array($data) || ($data !== [] && array_keys($data) === range(0, count($data) - 1))) { throw new ImportInvalid('invalid_file', __('This file does not look like an export of Admin Options Pages.', 'admin-options-pages')); } $data = self::toCurrentVersion($data); $errors = SchemaValidator::validate($data, self::schema()); if ($errors) { throw new ImportInvalid( 'invalid_file', __('This file does not look like an export of Admin Options Pages.', 'admin-options-pages'), $errors ); } $data['options'] = (array) ($data['options'] ?? []); return $data; } /** * Files of a lower version are migrated, files of a higher version are refused. * * Version 0 is the file of 0.9.x: no version, and per menu also the row `id` and `time`, which mean nothing on * another site. * * @throws ImportInvalid */ private static function toCurrentVersion(array $data): array { if (! array_key_exists('aop_export_version', $data)) { if (! isset($data['menus_and_pages']) || ! is_array($data['menus_and_pages'])) { throw new ImportInvalid('invalid_file', __('This file does not look like an export of Admin Options Pages.', 'admin-options-pages')); } $menus = []; foreach ($data['menus_and_pages'] as $item) { $menus[] = is_array($item) ? array_intersect_key($item, ['menu_slug' => 1, 'page_value' => 1]) : $item; } return [ 'aop_export_version' => Exporter::VERSION, 'menus_and_pages' => $menus, 'options' => $data['options'] ?? [], ]; } $version = $data['aop_export_version']; if (is_int($version) && $version > Exporter::VERSION) { throw new ImportInvalid( 'newer_version', sprintf( /* translators: 1: the version of the file, 2: the version this plugin reads */ __('This file has export format %1$d. This version of the plugin reads format %2$d. Update the plugin on this site and try again.', 'admin-options-pages'), $version, Exporter::VERSION ) ); } return $data; } private static function schema(): array { $file = \AOP\App\Plugin::root() . 'includes/schema/export.v1.json'; return (array) json_decode((string) file_get_contents($file), true); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- a file of the plugin } }