Skip to content
Snippets Groups Projects
Select Git revision
  • 1d041d52a37cf4d2820965e741d7291f155f319f
  • main default protected
  • studip-rector
  • ci-opt
  • course-members-export-as-word
  • data-vue-app
  • pipeline-improvements
  • webpack-optimizations
  • rector
  • icon-renewal
  • http-client-and-factories
  • jsonapi-atomic-operations
  • vueify-messages
  • tic-2341
  • 135-translatable-study-areas
  • extensible-sorm-action-parameters
  • sorm-configuration-trait
  • jsonapi-mvv-routes
  • docblocks-for-magic-methods
19 results

I18NString.php

Blame
  • Forked from Stud.IP / Stud.IP
    Source project has a limited visibility.
    Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    I18NString.php 11.46 KiB
    <?php
    
    /**
     * I18NString class
     */
    class I18NString implements JsonSerializable
    {
        /**
         * Text in default content language.
         *
         * @var string
         */
        protected $base;
    
        /**
         * Text in additional languages.
         *
         * @var array|null
         */
        protected $lang;
    
        /**
         * Database info for id, table, field.
         *
         * @var array
         */
        protected $metadata;
    
        /**
         * Holds the language the content is translated into.
         *
         * @var string
         */
        protected static $content_language = null;
    
        /**
         * Holds the language the content is translated into by default.
         *
         * @var string
         */
        protected static $default_language = null;
    
        /**
         * Initialize a new I18NString instance.
         *
         * @param string    $base   Text in default content language.
         * @param array     $lang   Text in additional languages.
         * @param array     $metadata Database info for id, table, field.
         */
        public function __construct($base, $lang = null, $metadata = [])
        {
            $this->base = $base;
            $this->lang = $lang;
            $this->metadata = $metadata;
        }
    
        /**
         * Return the text representation of this i18n field in selected language.
         * The language is selected by self::content_language (with precendence)
         * or by $_SESSION['_language'].
         *
         * @returns string
         */
        public function __toString()
        {
            if (self::$content_language) {
                return $this->localized(self::$content_language) ?? (string) $this->base;
            } else {
                if (isset($_SESSION['_language'])
                    && $_SESSION['_language'] != self::getDefaultLanguage()
                    && $this->translation($_SESSION['_language'])) {
                        return $this->translation($_SESSION['_language']);
                }
            }
    
            return (string) $this->base;
        }
    
        /**
         * Return the JSON representation of this i18n field in selected language.
         *
         * @return string
         */
        public function jsonSerialize()
        {
            return (string) $this;
        }
    
        /**
         * Sets the language the content is translated into.
         *
         * @param string $language
         */
        public static function setContentLanguage($language)
        {
            self::$content_language = $language;
        }
    
        /**
         * Returns the language the contnet is translated into.
         *
         * @return string The language the content is translated into.
         */
        public static function getContentLanguage()
        {
            return self::$content_language ?: self::getDefaultLanguage();
        }
    
        /**
         * Sets the default language the content is translated into. The default is
         * normally defined by the first entry in $GLOBALS['CONTENT_LANGUAGES'] (see
         * config_defaults.inc.php).
         *
         * @param string $language
         */
        public static function setDefaultLanguage($language = null)
        {
            self::$default_language = $language ?: key($GLOBALS['CONTENT_LANGUAGES']);
        }
    
        /**
         * Returns the language all values are translated into by default. The
         * language ist normally defined in $GLOBALS['CONTENT_LANGUAGES'] (see
         * config_defaults.inc.php).
         *
         * @return string The default language all values are translated into.
         */
        public static function getDefaultLanguage()
        {
            return self::$default_language ?: key($GLOBALS['CONTENT_LANGUAGES']);
        }
    
        /**
         * Sets the original (untranslated) value of this i18n field.
         *
         * @param string $text The original value.
         * @return string The original value.
         */
        public function setOriginal($text)
        {
            return $this->base = $text;
        }
    
        /**
         * Sets all translations of this i18n field.
         *
         * @param array $lang An array with languages as keys and translations
         * as values.
         * @return array The array with translations.
         */
        public function setTranslations($lang)
        {
            return $this->lang = $lang;
        }
    
        /**
         * Sets the metadata (database info for id, table, field) of this i18n field.
         *
         * @param array $metadata Database info for id, table, field.
         */
        public function setMetadata($metadata)
        {
            $this->metadata = $metadata;
        }
    
        /**
         * Return the string in the default content language.
         *
         * @return string String in default content language.
         */
        public function original()
        {
            return $this->base;
        }
    
        /**
         * Return the string in the specified additional language.
         *
         * @param string The additional language.
         * @return string The translated value.
         */
        public function translation($lang)
        {
            return $this->toArray()[$lang];
        }
    
        /**
         * Returns the string in the specified language (additional languages and
         * default languages).
         *
         * @param string $lang Additional language or default language.
         * @return string The localized string.
         */
        public function localized($lang)
        {
            if ($lang == self::getDefaultLanguage()) {
                return $this->base;
            }
    
            return $this->translation($lang);
        }
    
        /**
         * Sets the translation for the given language. If the given language is
         * the default language, sets the original.
         *
         * @param type $text The translated or original value.
         * @param type $lang The additional or default language.
         * @return string The translated or original value.
         * @throws InvalidArgumentException
         */
        public function setLocalized($text, $lang)
        {
            if ($lang == self::getDefaultLanguage()) {
                return $this->setOriginal($text);
            }
    
            if (!Config::get()->CONTENT_LANGUAGES[$lang]) {
                throw new InvalidArgumentException('Language not configured.');
            }
    
            return $this->lang[$lang] = $text;
        }
    
        /**
         * Return an array containing the text in all additional languages.
         *
         * @return array The array with translations.
         */
        public function toArray()
        {
            if (is_null($this->lang)) {
                $object_id = $this->metadata['object_id'];
                $table = $this->metadata['table'];
                $field =  $this->metadata['field'];
                if (!$table || !$field) {
                    throw new RuntimeException('fetching translations not possible, metadata is missing');
                }
                $this->lang = self::fetchDataForField($object_id, $table, $field);
            }
            return $this->lang;
        }
    
        /**
         * Trim all language strings
         *
         * @param string $symbols All symbols to trim.
         * @return I18NString Returns this.
         */
        public function trim($symbols = " \t\n\r\0\x0B")
        {
            foreach ($this->lang as &$lang) {
                $lang = trim($lang, $symbols);
            }
            $this->base = trim($this->base, $symbols);
            return $this;
        }
    
        /**
         * Stores the i18n String manually in the database
         *
         */
        public function storeTranslations()
        {
            if (is_array($this->lang)) {
                $db = DBManager::get();
                $object_id = $this->metadata['object_id'];
                $table = $this->metadata['table'];
                $field = $this->metadata['field'];
                if (!$object_id || !$table || !$field) {
                    throw new RuntimeException('store not possible, metadata is missing');
                }
                /* Replace translations */
                $deleted = $db->execute("DELETE FROM i18n WHERE object_id = ? AND `table` = ? AND field = ?", [$object_id, $table, $field]);
                $i18nSQL = $db->prepare("INSERT INTO `i18n` (`object_id`, `table`, `field`, `lang`, `value`) VALUES (?,?,?,?,?)");
                foreach ($this->lang as $lang => $value) {
                    if (mb_strlen($value)) {
                        $i18nSQL->execute([$object_id, $table, $field, $lang, (string) $value]);
                    }
                }
            }
        }
    
        /**
         * Removes all translations for this I18NString object.
         *
         */
        public function removeTranslations()
        {
            $this->lang = [];
            $this->storeTranslations();
        }
    
        /**
         * Returns an I18NString object by given object_id, table and field.
         *
         * @param string $object_id The id of the object with i18n fields.
         * @param string $table The name of the table with the original values.
         * @param string $field The name of the i18n field.
         * @param string $base Sets the original value or retrieve it from database
         * if null.
         * @return I18NString The I18NString object.
         */
        public static function load($object_id, $table, $field, $base = null)
        {
            $db = DBManager::get();
            if (is_null($base)) {
                // Find pk
                SimpleORMap::tableScheme($table);
                if (count(SimpleORMap::$schemes[$table]['pk']) > 1) {
                    throw new RuntimeException(sprintf('table %s has multiple primary key, not implemented yet', $table));
                } else {
                    $pk = SimpleORMap::$schemes[$table]['pk'][0];
                }
                $base = $db->fetchColumn("SELECT `$field` FROM `$table` WHERE `$pk` = ?", [$object_id]);
            }
            return new self($base, self::fetchDataForField($object_id, $table, $field), compact('object_id', 'table', 'field'));
        }
    
        /**
         * Retrieves all translations of one field.
         *
         * @param string $object_id The id of the object with i18n fields.
         * @param string $table The name of the table with the original values.
         * @param string $field The name of the i18n field.
         * @return array An array with language as key and translation as value.
         */
        public static function fetchDataForField($object_id, $table, $field)
        {
            $db = DBManager::get();
            $values = $db->fetchPairs("SELECT `lang`, `value` FROM `i18n` WHERE `object_id` = ? AND `table` = ? AND `field` = ?", [$object_id, $table, $field]);
            $data = [];
            foreach (array_keys(Config::get()->CONTENT_LANGUAGES) as $lang) {
                if ($lang != self::getDefaultLanguage()) {
                    $data[$lang] = mb_strlen($values[$lang]) ? $values[$lang] : null;
                }
            }
            return $data;
        }
    
        /**
         * Retrieves all translations of all fields for given object (by id) and
         * table.
         *
         * @param string $object_id The id of the object with i18n fields.
         * @param string $table The name of the table with the original values.
         * @return array An array with all translations of all fields grouped by
         * field.
         */
        public static function fetchDataForRow($object_id, $table)
        {
            $db = DBManager::get();
            return $db->fetchGrouped("SELECT `field`, `lang`, `value` FROM `i18n` WHERE `object_id` = ? AND `table` = ?", [$object_id, $table]);
        }
    
        /**
         * Removes all translations by given object id and table name. Accepts the
         * language as third parameter to remove only translations to this language.
         *
         * @param string $object_id The id of the sorm object.
         * @param string $table The table name.
         * @param string $lang Optional name of language.
         * @return int The number of deleted translations.
         */
        public static function removeAllTranslations($object_id, $table, $lang = null)
        {
            $db = DBManager::get();
            if ($lang) {
                return $db->execute('DELETE FROM `i18n` '
                        . 'WHERE `object_id` = ? AND `table` = ? AND `lang` = ?',
                        [$object_id, $table, $lang]);
            }
            return $db->execute('DELETE FROM `i18n` '
                    . 'WHERE `object_id` = ? AND `table` = ?',
                    [$object_id, $table]);
        }
    }