$data Сырые данные из wp_options. * @param bool $isDefault Является ли язык языком по умолчанию. */ public static function fromArray( array $data, bool $isDefault ): self { $locale = Locale::normalize( (string) ( $data['locale'] ?? '' ) ); $slug = Locale::normalizeSlug( (string) ( $data['slug'] ?? $locale ) ); $label = trim( (string) ( $data['label'] ?? '' ) ); $status = ( $data['status'] ?? self::STATUS_PUBLISHED ) === self::STATUS_DRAFT ? self::STATUS_DRAFT : self::STATUS_PUBLISHED; /* * Локаль WordPress выводится из кода языка, только если её нет в * настройках вовсе — то есть у языков, заведённых до появления * этого поля. Так обновление плагина ничего не перезаписывает * молча: сохранённое значение всегда сильнее вычисленного, а у * кого его нет, тот получает разумный дефолт вместо пустоты. */ $wpLocale = Locale::sanitizeWpLocale( (string) ( $data['wp_locale'] ?? '' ) ); if ( ! Locale::isValidWpLocale( $wpLocale ) ) { $wpLocale = Locale::toWpLocale( $locale ); } return new self( $locale, '' !== $slug ? $slug : $locale, '' !== $label ? $label : $locale, // Язык по умолчанию всегда доступен: черновиком он быть не может. $isDefault ? self::STATUS_PUBLISHED : $status, $isDefault, self::sanitizeFlag( (string) ( $data['flag'] ?? '' ) ), $wpLocale ); } /** * Приводит значение флага к безопасному виду. Чистая функция. * * Не проверяет, что это именно emoji-флаг (символ ×256 не отличить от * буквы средствами PHP без библиотеки Unicode-свойств) — только режет * длину и убирает теги, чтобы поле нельзя было превратить в HTML-инъекцию * в шаблонах, где флаг выводится без дополнительного экранирования. * * @param string $flag Сырое значение поля. */ public static function sanitizeFlag( string $flag ): string { $flag = trim( wp_strip_all_tags( $flag ) ); return mb_substr( $flag, 0, self::MAX_FLAG_LENGTH ); } /** * Опубликован ли язык (есть ли у него доступный URL и hreflang). */ public function isPublished(): bool { return self::STATUS_PUBLISHED === $this->status; } /** * Значение для атрибутов `lang` и `hreflang`. */ public function bcp47(): string { return Locale::toBcp47( $this->locale ); } /** * Короткий код языка для переключателя: `RU`, `EN`, `PT-BR`. * * Именно код языка, а не слаг и не локаль WordPress: слаг владелец * сайта может задать любой (`/en/` против `/english/`), а `ru_RU` * посетителю ничего не говорит. */ public function switcherCode(): string { return strtoupper( $this->locale ); } /** * Название с флагом впереди, если он задан — готовая подпись для * переключателя, без пляски с проверкой пустой строки в шаблонах. */ public function labelWithFlag(): string { return '' !== $this->flag ? $this->flag . ' ' . $this->label : $this->label; } /** * Представление для сохранения в wp_options. * * @return array */ public function toArray(): array { return array( 'locale' => $this->locale, 'slug' => $this->slug, 'label' => $this->label, 'status' => $this->status, 'flag' => $this->flag, 'wp_locale' => $this->wpLocale, ); } }