public function testSetLanguage()
 {
     $obj = new TranslationConfig(['languages' => ['en', 'fr']]);
     $this->assertSame('en', $obj->currentLanguage());
     $ret = $obj->setCurrentLanguage('fr');
     $this->assertSame($ret, $obj);
     $this->assertEquals('fr', $obj->currentLanguage());
     $this->setExpectedException('\\InvalidArgumentException');
     $obj->setCurrentLanguage('foobar-lang');
 }
 /**
  * @return array
  */
 public function choices()
 {
     $translator = TranslationConfig::instance();
     $choices = [];
     foreach ($translator->languages() as $langCode => $langObj) {
         $label = (string) $langObj->name();
         if (empty($label)) {
             $label = (string) $langObj;
         }
         $choices[] = ['label' => $label, 'selected' => $this->val() === $langCode, 'value' => $langCode];
     }
     return $choices;
 }
 /**
  * Reset the property's storage fields.
  *
  * @param  mixed $val The value to set as field value.
  * @return PropertyField[]
  */
 private function generateFields($val)
 {
     $this->fields = [];
     if ($this->l10n()) {
         $translator = TranslationConfig::instance();
         foreach ($translator->availableLanguages() as $langCode) {
             $ident = sprintf('%1$s_%2$s', $this->ident(), $langCode);
             $field = new PropertyField();
             $field->setData(['ident' => $ident, 'sqlType' => $this->sqlType(), 'sqlPdoType' => $this->sqlPdoType(), 'extra' => $this->sqlExtra(), 'val' => $this->fieldVal($langCode, $val), 'defaultVal' => null, 'allowNull' => $this->allowNull()]);
             $this->fields[$langCode] = $field;
         }
     } else {
         $field = new PropertyField();
         $field->setData(['ident' => $this->ident(), 'sqlType' => $this->sqlType(), 'sqlPdoType' => $this->sqlPdoType(), 'extra' => $this->sqlExtra(), 'val' => $this->storageVal($val), 'defaultVal' => null, 'allowNull' => $this->allowNull()]);
         $this->fields[] = $field;
     }
     return $this->fields;
 }
 /**
  * @param mixed $val Optional. The value to display. If null/unset, use `val()`.
  * @return string
  * @see AbstractProperty::displayVal()
  */
 public function displayVal($val)
 {
     if ($val === null) {
         return '';
     }
     $propertyValue = $val;
     if ($this->l10n()) {
         $translator = TranslationConfig::instance();
         $propertyValue = $propertyValue[$translator->currentLanguage()];
     }
     if ($this->multiple()) {
         if (is_array($propertyValue)) {
             $props = [];
             foreach ($propertyValue as $pv) {
                 $props[] = $this->valLabel($pv);
             }
             $propertyValue = implode($this->multipleSeparator(), $props);
         }
     } else {
         $propertyValue = (string) $propertyValue;
         $propertyValue = $this->valLabel($propertyValue);
     }
     return $propertyValue;
 }
 /**
  * @param string|array|Order $param        The order property, or an Order object / array.
  * @param string             $mode         Optional.
  * @param array              $orderOptions Optional.
  * @throws InvalidArgumentException If the param argument is invalid.
  * @return CollectionLoader Chainable
  */
 public function addOrder($param, $mode = 'asc', array $orderOptions = null)
 {
     if ($param instanceof OrderInterface) {
         $order = $param;
     } elseif (is_array($param)) {
         $order = $this->createOrder();
         $order->setData($param);
     } elseif (is_string($param)) {
         $order = $this->createOrder();
         $order->setProperty($param);
         $order->setMode($mode);
         if (isset($orderOptions['values'])) {
             $order->setValues($orderOptions['values']);
         }
     } else {
         throw new InvalidArgumentException('Parameter must be an OrderInterface object or a property ident.');
     }
     if ($this->hasModel()) {
         $property = $order->property();
         if ($property) {
             $p = $this->model()->p($property);
             if ($p) {
                 if ($p->l10n()) {
                     $translator = TranslationConfig::instance();
                     $ident = sprintf('%1$s_%2$s', $property, $translator->currentLanguage());
                     $order->setProperty($ident);
                 }
             }
         }
     }
     $this->orders[] = $order;
     return $this;
 }
 /**
  * Retrieve a Charcoal application's instance or a new instance of self.
  *
  * @see    ConfigurableInterface::create_config() For abstract definition of this method.
  * @uses   TranslationConfig::instance()
  * @param  array|string|null $data Optional data to pass to the new TranslationConfig instance.
  * @return TranslationConfig
  */
 protected function createConfig($data = null)
 {
     $config = TranslationConfig::instance($data);
     return $config;
 }
 /**
  * @return GenericRoute Chainable
  */
 protected function resolveTemplateContextObject()
 {
     $config = $this->config();
     $objectRoute = $this->loadObjectRouteFromPath();
     $contextObject = $this->loadContextObject();
     // Set language according to the route's language
     $translator = TranslationConfig::instance();
     $translator->setCurrentLanguage($objectRoute->lang());
     $templateChoice = [];
     // Templateable Objects have specific methods
     if ($contextObject instanceof TemplateableInterface) {
         $identProperty = $contextObject->property('template_ident');
         $controllerProperty = $contextObject->property('controller_ident');
         // Methods from TemplateableInterface / Trait
         $templateIdent = $contextObject->templateIdent() ?: $objectRoute->routeTemplate();
         // Default fallback to routeTemplate
         $controllerIdent = $contextObject->controllerIdent() ?: $templateIdent;
         $templateChoice = $identProperty->choice($templateIdent);
     } else {
         // Use global templates to verify for custom paths
         $templateIdent = $objectRoute->routeTemplate();
         $controllerIdent = $templateIdent;
         foreach ($this->availableTemplates as $templateKey => $templateData) {
             if (!isset($templateData['value'])) {
                 $templateData['value'] = $templateKey;
             }
             if ($templateData['value'] === $templateIdent) {
                 $templateChoice = $templateData;
                 break;
             }
         }
     }
     // Template ident defined in template global config
     // Check for custom path / controller
     if (isset($templateChoice['template'])) {
         $templatePath = $templateChoice['template'];
         $templateController = $templateChoice['template'];
     } else {
         $templatePath = $templateIdent;
         $templateController = $controllerIdent;
     }
     // Template controller defined in choices, affect it.
     if (isset($templateChoice['controller'])) {
         $templateController = $templateChoice['controller'];
     }
     $config['template'] = $templatePath;
     $config['controller'] = $templateController;
     // Always be an array
     $templateOptions = [];
     // Custom template options
     if (isset($templateChoice['template_options'])) {
         $templateOptions = $templateChoice['template_options'];
     }
     // Overwrite from custom object template_options
     if ($contextObject instanceof TemplateableInterface) {
         if (!empty($contextObject->templateOptions())) {
             $templateOptions = $contextObject->templateOptions();
         }
     }
     if (isset($templateOptions) && $templateOptions) {
         // Not sure what this was about?
         $config['template_data'] = array_merge($config['template_data'], $templateOptions);
     }
     $this->setConfig($config);
     return $this;
 }
 /**
  * @param Container $container Pimple DI container.
  * @return \Charcoal\Cms\EventInterface
  */
 protected function loadEventFromPath(Container $container)
 {
     if (!$this->event) {
         $config = $this->config();
         $objType = isset($config['obj_type']) ? $config['obj_type'] : $this->objType;
         $this->event = $container['model/factory']->create($objType);
         $translator = TranslationConfig::instance();
         $langs = $translator->availableLanguages();
         $lang = $this->event->loadFromL10n('slug', $this->path, $langs);
         $translator->setCurrentLanguage($lang);
     }
     return $this->event;
 }
 /**
  * Retrieve the current property's client-side settings for elFinder.
  *
  * @return string Returns data serialized with {@see json_encode()}.
  */
 public function elfinderConfigAsJson()
 {
     $property = $this->formProperty();
     $settings = [];
     if ($this->elfinderConfig['client']) {
         $settings = $this->elfinderConfig['client'];
     }
     $translator = TranslationConfig::instance();
     $settings['lang'] = $translator->currentLanguage();
     if ($property) {
         $mimeTypes = filter_input(INPUT_GET, 'filetype', FILTER_SANITIZE_STRING);
         if ($mimeTypes) {
             if ($mimeTypes === 'file') {
                 $mimeTypes = [];
             }
             $settings['onlyMimes'] = (array) $mimeTypes;
         } elseif ($property instanceof FileProperty) {
             $settings['onlyMimes'] = $property->acceptedMimetypes();
         }
         $settings['rememberLastDir'] = !$property instanceof FileProperty;
     }
     return json_encode($settings, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
 }
 /**
  * Determine if the form control's active language should be displayed.
  *
  * @return boolean
  */
 public function showActiveLanguage()
 {
     $prop = $this->prop();
     $trans = TranslationConfig::instance();
     return $trans->isMultilingual() && $prop->l10n();
 }
 /**
  * Retrieve the latest object route.
  *
  * @param  string|null $lang If object is multilingual, return the object route for the specified locale.
  * @throws InvalidArgumentException If the given language is invalid.
  * @return ObjectRouteInterface Latest object route.
  */
 protected function getLatestObjectRoute($lang = null)
 {
     $translator = TranslationConfig::instance();
     if ($lang === null) {
         $lang = $translator->currentLanguage();
     } elseif (!$translator->hasLanguage($lang)) {
         throw new InvalidArgumentException(sprintf('Invalid language, received %s', is_object($lang) ? get_class($lang) : gettype($lang)));
     }
     if (isset($this->latestObjectRoute[$lang])) {
         return $this->latestObjectRoute[$lang];
     }
     $model = $this->createRouteObject();
     if (!$this->objType() || !$this->id()) {
         $this->latestObjectRoute[$lang] = $model;
         return $this->latestObjectRoute[$lang];
     }
     // For URL.
     $source = $model->source();
     $loader = new CollectionLoader(['logger' => $this->logger, 'factory' => $this->modelFactory()]);
     if (!$source->tableExists()) {
         $source->createTable();
     }
     $loader->setModel($model)->addFilter('route_obj_type', $this->objType())->addFilter('route_obj_id', $this->id())->addFilter('lang', $lang)->addFilter('active', true)->addOrder('creation_date', 'desc')->setPage(1)->setNumPerPage(1);
     $collection = $loader->load()->objects();
     if (!count($collection)) {
         $this->latestObjectRoute[$lang] = $model;
         return $this->latestObjectRoute[$lang];
     }
     $this->latestObjectRoute[$lang] = $collection[0];
     return $this->latestObjectRoute[$lang];
 }
 /**
  * Retrieve the available languages, formatted for the sidebar language-switcher.
  *
  * @return array|Generator
  */
 public function languages()
 {
     $trans = TranslationConfig::instance();
     $curLang = $trans->currentLanguage();
     $langs = $trans->languages();
     foreach ($langs as $lang) {
         (yield ['ident' => $lang->ident(), 'name' => $lang->name(), 'current' => $lang->ident() === $curLang]);
     }
 }
 /**
  * @param mixed $val Optional. The value to display.
  * @return string
  */
 public function displayVal($val)
 {
     if ($val === null) {
         return '';
     }
     $propertyValue = $val;
     if ($this->l10n() === true) {
         $translator = TranslationConfig::instance();
         $propertyValue = $propertyValue[$translator->currentLanguage()];
     }
     if ($this->multiple() === true) {
         if (!is_array($propertyValue)) {
             $propertyValue = explode($this->multipleSeparator(), $propertyValue);
         }
     } else {
         $propertyValue = [$propertyValue];
     }
     $names = [];
     foreach ($propertyValue as $objIdent) {
         $obj = $this->loadObject($objIdent);
         if ($obj === null) {
             continue;
         }
         $names[] = $this->objPattern($obj);
     }
     return implode(', ', $names);
 }
 /**
  * Registers services on the given container.
  *
  * This method should only be used to configure services and parameters.
  * It should not get services.
  *
  * @todo   [mcaskill 2016-02-11] Implement translation drivers (Database, File, Yandex)
  *         similar to CacheServiceProvider.
  * @todo   [mcaskill 2016-03-07] Implement a 'setCurrentLanguage' that will update
  *         the environment's locale and our Container's TranslationConfig singeton.
  *         For now, you need to call:
  *
  *         ```php
  *         // Handles setlocale()
  *         $container['translator/config']->setCurrentLanguage($lang);
  *
  *         // Handles ConfigurableTranslationTrait
  *         $container['translator/locales']->setCurrentLanguage($lang);
  *         ```
  * @param  Container $container The container instance.
  * @throws RuntimeException If no active languages are provided or translations are not valid.
  * @return void
  */
 public function register(Container $container)
 {
     $container['translator/config'] = function (Container $container) {
         $appConfig = $container['config'];
         $translatorConfig = new TranslatorConfig();
         if ($appConfig->has('translator')) {
             $translatorConfig->merge($appConfig->get('translator'));
         }
         if ($appConfig->has('locales')) {
             $translatorConfig->setLocales($appConfig->get('locales'));
         }
         if ($appConfig->has('translations')) {
             $translatorConfig->setTranslations($appConfig->get('translations'));
         }
         return $translatorConfig;
     };
     $container['translator/language-repository'] = function (Container $container) {
         $config = $container['translator/config']->locales();
         $loader = new LanguageRepository();
         $loader->setDependencies($container);
         $loader->setPaths($config['repositories']);
         return $loader;
     };
     $container['translator/resource-repository'] = function (Container $container) {
         $config = $container['translator/config']->translations();
         $loader = new ResourceRepository();
         $loader->setDependencies($container);
         $loader->setPaths($config['paths']);
         return $loader;
     };
     $container['translator/locales'] = function (Container $container) {
         $repo = $container['translator/language-repository'];
         $config = $container['translator/config']->locales();
         $langs = array_filter($config['languages'], function ($lang) {
             return !isset($lang['active']) || $lang['active'];
         });
         if ($langs) {
             $index = $repo->load(array_keys($langs));
             foreach ($langs as $ident => $data) {
                 $lang = new Language();
                 if (!is_array($data)) {
                     $data = [];
                 }
                 if (isset($index[$ident])) {
                     $data = array_merge($index[$ident], $data);
                 }
                 if (!isset($data['ident'])) {
                     $lang->setIdent($ident);
                 }
                 $lang->setData($data);
                 $langs[$lang->ident()] = $lang;
             }
             $config['languages'] = $langs;
         } else {
             throw new RuntimeException('At least one language must be active (e.g., `$langCode => $langInfo`).');
         }
         $object = new TranslationConfig($config);
         return $object;
     };
     $container['translator/catalog'] = function (Container $container) {
         $repo = $container['translator/resource-repository'];
         $langs = $container['translator/locales']->availableLanguages();
         $config = $container['translator/config']->translations();
         /**
          * Build the array of Language objects from the `TranslationConfig`-filtered list
          * to prevent any bad apples from slipping through.
          */
         $translations = [];
         if (isset($config['messages'])) {
             if (is_array($config['messages'])) {
                 $translations = $config['messages'];
             } else {
                 throw new RuntimeException('Global translations must be an associative array (e.g., `$ident => $translations`).');
             }
         }
         $catalog = new Catalog($translations);
         $repo->setCatalog($catalog);
         if ($langs) {
             $repo->setLanguages($langs);
             $translations = $repo->load();
             if ($translations) {
                 $catalog->addResources($translations);
             }
         }
         return $catalog;
     };
     $container['translator'] = function (Container $container) {
         return [];
     };
     /**
      * @todo Figure this shit out!
      */
     TranslationConfig::setInstance($container['translator/locales']);
 }
 /**
  * The display name should always be the property's ident.
  *
  * @return string
  */
 public function displayName()
 {
     $name = $this->p()->ident();
     if ($this->multiple()) {
         $name .= '[]';
     }
     if ($this->p()->l10n()) {
         $lang = TranslationConfig::instance()->currentLanguage();
         $name .= '[' . $lang . ']';
     }
     return $name;
 }
 /**
  * @return boolean
  */
 public function hidden()
 {
     if ($this->p()->l10n()) {
         if ($this->lang() != TranslationConfig::instance()->currentLanguage()) {
             return true;
         }
     }
     return false;
 }