Author: Damian Mooyman (damian.mooyman@gmail.com)
Inheritance: extends Object, implements TemplateGlobalProvider
    public function fix_fluent_menu()
    {
        if (!class_exists('Fluent')) {
            return;
        }
        $conf = SiteConfig::current_site_config();
        $localesNames = Fluent::locale_names();
        if ($conf->hasExtension('ActiveLocalesExtension') && $conf->ActiveLocales) {
            $localesNames = $conf->ActiveLocalesNames();
        }
        $locales = json_encode($localesNames);
        $locale = json_encode(Fluent::current_locale());
        // If we have only one locale, set this one as default
        if (count($localesNames) === 1) {
            $locale = json_encode(key($localesNames));
        }
        $param = json_encode(Fluent::config()->query_param);
        $buttonTitle = json_encode(_t('Fluent.ChangeLocale', 'Change Locale'));
        Requirements::block('FluentHeadScript');
        Requirements::insertHeadTags(<<<EOT
<script type="text/javascript">
//<![CDATA[
\tvar fluentLocales = {$locales};
\tvar fluentLocale = {$locale};
\tvar fluentParam = {$param};
\tvar fluentButtonTitle = {$buttonTitle};
//]]>
</script>
EOT
, 'FluentHeadScriptSubsite');
    }
 public function augmentSQL(SQLQuery &$query, DataQuery &$dataQuery = null)
 {
     // When filtering my menu, swap out condition for locale specific condition
     $locale = Fluent::current_locale();
     $field = Fluent::db_field_for_locale("ShowInMenus", $locale);
     $query->replaceText("\"{$this->ownerBaseClass}\".\"ShowInMenus\"", "\"{$this->ownerBaseClass}\".\"{$field}\"");
 }
 /**
  * Retrieves information about this object in the CURRENT locale
  *
  * @param string $locale The locale information to request, or null to use the default locale
  * @return ArrayData Mapped list of locale properties
  */
 public function CurrentLocaleInformation()
 {
     $locale = Fluent::current_locale();
     // Store basic locale information
     $data = array('Locale' => $locale, 'LocaleRFC1766' => i18n::convert_rfc1766($locale), 'Alias' => Fluent::alias($locale), 'Title' => i18n::get_locale_name($locale), 'LanguageNative' => i18n::get_language_name(i18n::get_lang_from_locale($locale), true));
     return new ArrayData($data);
 }
 public function preRequest(SS_HTTPRequest $request, Session $session, DataModel $model)
 {
     // Ensures routes etc are setup
     // We need to inject the presented session temporarily, as there is no current controller set
     FluentSession::with_session($session, function () {
         Fluent::init();
     });
 }
 public function updateCMSFields(FieldList $fields)
 {
     parent::updateCMSFields($fields);
     // Fix URLSegment field issue for root pages
     if (!SiteTree::config()->nested_urls || empty($this->owner->ParentID)) {
         $baseLink = Director::absoluteURL(Controller::join_links(Director::baseURL(), Fluent::alias(Fluent::current_locale()), '/'));
         $urlsegment = $fields->dataFieldByName('URLSegment');
         $urlsegment->setURLPrefix($baseLink);
     }
 }
    public function init()
    {
        $dirName = basename(dirname(dirname(dirname(__FILE__))));
        $locales = json_encode(Fluent::locale_names());
        $locale = json_encode(Fluent::current_locale());
        $param = json_encode(Fluent::config()->query_param);
        $buttonTitle = json_encode(_t('Fluent.ChangeLocale', 'Change Locale'));
        // Force the variables to be written to the head, to ensure these are available for other scripts to pick up.
        Requirements::insertHeadTags(<<<EOT
<script type="text/javascript">
//<![CDATA[
\tvar fluentLocales = {$locales};
\tvar fluentLocale = {$locale};
\tvar fluentParam = {$param};
\tvar fluentButtonTitle = {$buttonTitle};
//]]>
</script>
EOT
, 'FluentHeadScript');
        Requirements::javascript("{$dirName}/javascript/fluent.js");
        Requirements::css("{$dirName}/css/fluent.css");
    }
 public function handleRequest(SS_HTTPRequest $request, DataModel $model = null)
 {
     self::$is_at_root = true;
     $this->setDataModel($model);
     $this->pushCurrent();
     $this->init();
     $this->setRequest($request);
     // Check for existing routing parameters, redirecting to another locale automatically if necessary
     $locale = Fluent::get_request_locale();
     if (empty($locale)) {
         // Determine if this user should be redirected
         $locale = $this->getRedirectLocale();
         $this->extend('updateRedirectLocale', $locale);
         // Check if the user should be redirected
         $domainDefault = Fluent::default_locale(true);
         if (Fluent::is_locale($locale) && $locale !== $domainDefault) {
             // Check new traffic with detected locale
             return $this->redirect(Fluent::locale_baseurl($locale));
         }
         // Reset parameters to act in the default locale
         $locale = $domainDefault;
         Fluent::set_persist_locale($locale);
         $params = $request->routeParams();
         $params[Fluent::config()->query_param] = $locale;
         $request->setRouteParams($params);
     }
     if (!DB::isActive() || !ClassInfo::hasTable('SiteTree')) {
         $this->response = new SS_HTTPResponse();
         $this->response->redirect(Director::absoluteBaseURL() . 'dev/build?returnURL=' . (isset($_GET['url']) ? urlencode($_GET['url']) : null));
         return $this->response;
     }
     $localeURL = Fluent::alias($locale);
     $request->setUrl(self::fluent_homepage_link($localeURL));
     $request->match($localeURL . '/$URLSegment//$Action', true);
     $controller = new ModelAsController();
     $result = $controller->handleRequest($request, $model);
     $this->popCurrent();
     return $result;
 }
function get_silverstripe_language()
{
    $locale = i18n::get_locale();
    if (class_exists('Fluent')) {
        $locale = Fluent::get_persist_locale();
    }
    $lang = i18n::get_lang_from_locale($locale);
    if ($lang == 'en') {
        return 'en_EN';
    }
    if ($lang == 'fr') {
        return 'fr_FR';
    }
    // Otherwise look in lang folder
    $ulocale = str_replace('-', '_', $locale);
    $lang_folder = dirname(__DIR__) . '/lang/';
    if (is_file($lang_folder . $lang . '.php')) {
        return $lang;
    }
    if (is_file($lang_folder . $ulocale . '.php')) {
        return $ulocale;
    }
    return 'en_EN';
}
 /**
  * Set/Install the given locale.
  * This does set the i18n locale as well as the Translatable or Fluent locale (if any of these modules is installed)
  * @param string $locale the locale to install
  * @throws Zend_Locale_Exception @see Zend_Locale_Format::getDateFormat and @see Zend_Locale_Format::getTimeFormat
  */
 public static function install_locale($locale)
 {
     // If the locale isn't given, silently fail (there might be carts that still have locale set to null)
     if (empty($locale)) {
         return;
     }
     if (class_exists('Translatable')) {
         Translatable::set_current_locale($locale);
     } else {
         if (class_exists('Fluent')) {
             Fluent::set_persist_locale($locale);
         }
     }
     // Do something like Fluent does to install the locale
     i18n::set_locale($locale);
     // LC_NUMERIC causes SQL errors for some locales (comma as decimal indicator) so skip
     foreach (array(LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_TIME) as $category) {
         setlocale($category, "{$locale}.UTF-8", $locale);
     }
     // Get date/time formats from Zend
     require_once 'Zend/Date.php';
     i18n::config()->date_format = Zend_Locale_Format::getDateFormat($locale);
     i18n::config()->time_format = Zend_Locale_Format::getTimeFormat($locale);
 }
Example #10
0
 /**
  * 系统错误,可直接将Exception对象传给$msg
  * @param string/Exception $msg
  */
 public static function show_500($msg = null)
 {
     Core::close_buffers(false);
     # 避免输出的CSS头试抛出页面无法显示
     @header('Content-Type: text/html;charset=' . Core::config('charset'), true);
     HttpIO::$status = 500;
     HttpIO::send_headers();
     if (null === $msg) {
         $msg = __('Internal Server Error');
     }
     if (IS_DEBUG && class_exists('DevException', false)) {
         if ($msg instanceof Exception) {
             $e = $msg;
         } else {
             $e = new Exception($msg);
         }
         echo DevException::exception_handler($e, true);
         exit;
     }
     if (IS_CLI) {
         echo "", $msg, CRLF, "", CRLF;
         exit;
     }
     try {
         if ($msg instanceof Exception) {
             $error = $msg->getMessage();
             $trace_obj = $msg;
         } else {
             $error = $msg;
             $trace_obj = new Exception($msg);
         }
         $error_config = Core::config('error500');
         $view = new View('error/500');
         if ($error_config && isset($error_config['close']) && $error_config['close'] == true) {
             # 不记录
             $view->error_saved = false;
             $error_no = '';
         } else {
             $trace_array = array('project' => Core::$project, 'admin_mode' => IS_ADMIN_MODE, 'uri' => HttpIO::$uri, 'url' => HttpIO::PROTOCOL . $_SERVER['HTTP_HOST'] . $_SERVER["REQUEST_URI"], 'post' => HttpIO::POST(null, HttpIO::PARAM_TYPE_OLDDATA), 'get' => $_SERVER['QUERY_STRING'], 'cookie' => HttpIO::COOKIE(null, HttpIO::PARAM_TYPE_OLDDATA), 'client_ip' => HttpIO::IP, 'user_agent' => HttpIO::USER_AGENT, 'referrer' => HttpIO::REFERRER, 'server_ip' => $_SERVER["SERVER_ADDR"]);
             $date = @date('Y-m-d');
             $no = strtoupper(substr(md5(serialize($trace_array)), 10, 10));
             $error_no = $date . '-' . $no;
             # 其它数据
             $trace_array['server_name'] = function_exists('php_uname') ? php_uname('a') : 'unknown';
             $trace_array['time'] = TIME;
             $trace_array['use_time'] = microtime(1) - START_TIME;
             $trace_array['trace'] = (string) $trace_obj;
             $trace_string = Core::json_encode($trace_array);
             $view->error_saved = true;
             # 记录错误日志
             try {
                 if (isset($error_config['save_type']) && $error_config['save_type']) {
                     $save_type = $error_config['save_type'];
                 } else {
                     $save_type = 'file';
                 }
                 if ($save_type === 'file') {
                     # 文件模式
                     $write_mode = Core::config('file_write_mode');
                     if (preg_match('#^(db|cache|fluent)://(([a-z0-9\\.\\-_]+)(?:\\:|/)([a-z0-9_]+))$#i', $write_mode, $m)) {
                         $save_type = $m[1];
                         $error_config['server'] = $m[2];
                         $error_config['type_config'] = $m[3];
                     }
                 }
                 switch ($save_type) {
                     case 'database':
                         $obj = $error_config['type_config'] ? new Database($error_config['type_config']) : new Database();
                         $data = array('time' => strtotime($date . ' 00:00:00'), 'no' => $no, 'log' => $obj->is_support_object_value() ? $trace_array : $trace_string, 'expire_time' => TIME + 7 * 86400);
                         $obj->insert('error500_log', $data);
                         break;
                     case 'cache':
                         $obj = $error_config['type_config'] ? new Cache($error_config['type_config']) : new Cache();
                         if (!$obj->get($error_no)) {
                             $obj->set($error_no, $trace_string, 7 * 86400);
                         }
                         break;
                     case 'fluent':
                         if (strpos($error_config['server'], ':') !== false) {
                             $fd_server = 'tcp://' . $error_config['server'];
                         } else {
                             $fd_server = 'udp://' . $error_config['server'];
                         }
                         $obj = Fluent::instance($fd_server);
                         $obj->push('system.error500', $trace_array);
                         break;
                     default:
                         $file = DIR_LOG . 'error500' . DS . str_replace('-', DS, $date) . DS . $no . '.log';
                         if (!is_file($file)) {
                             File::create_file($file, date('Y-m-d\\TH:i:s') . ' - ' . $trace_string, null, null, $error_config['type_config'] ? $error_config['type_config'] : 'default');
                         }
                         break;
                 }
             } catch (Exception $e) {
             }
         }
         $view->error_no = $error_no;
         $view->error = $error;
         $view->render(true);
     } catch (Exception $e) {
         list($REQUEST_URI) = explode('?', $_SERVER['REQUEST_URI'], 2);
         $REQUEST_URI = htmlspecialchars(rawurldecode($REQUEST_URI));
         echo '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">' . CRLF . '<html>' . CRLF . '<head>' . CRLF . '<title>Internal Server Error</title>' . CRLF . '</head>' . CRLF . '<body>' . CRLF . '<h1>Internal Server Error</h1>' . CRLF . '<p>The requested URL ' . $REQUEST_URI . ' was error on this server.</p>' . CRLF . '<hr />' . CRLF . $_SERVER['SERVER_SIGNATURE'] . '<br/><br/><br/>' . CRLF . 'Powered by MyQEE V' . Core::VERSION . CRLF . '</body>' . CRLF . '</html>';
     }
     exit;
 }
 public function run($request)
 {
     echo 'Run with ?clear=1 to clear empty database before running the task<br/>';
     echo 'Run with ?overwrite=1 to overwrite templates that exists in the cms<br/>';
     echo 'Run with ?templates=xxx,yyy to specify which template should be imported<br/>';
     echo 'Run with ?subsite=1 to create email templates in all subsites as well. Overwriting is based on main site.<br/>';
     echo '<hr/>';
     $overwrite = $request->getVar('overwrite');
     $clear = $request->getVar('clear');
     $templatesToImport = $request->getVar('templates');
     $importToSubsite = $request->getVar('subsite');
     $subsites = array();
     if ($importToSubsite) {
         $subsites = Subsite::get()->map();
     }
     if ($templatesToImport) {
         $templatesToImport = explode(',', $templatesToImport);
     }
     if ($clear == 1) {
         echo '<strong>Clear all email templates</strong><br/>';
         $emailTemplates = EmailTemplate::get();
         foreach ($emailTemplates as $emailTemplate) {
             $emailTemplate->delete();
         }
     }
     $o = singleton('EmailTemplate');
     $ignoredModules = self::config()->ignored_modules;
     if (!is_array($ignoredModules)) {
         $ignoredModules = array();
     }
     $locales = null;
     if (class_exists('Fluent') && Fluent::locale_names()) {
         if ($o->hasExtension('FluentExtension')) {
             $locales = array_keys(Fluent::locale_names());
         }
     }
     $defaultLocale = i18n::get_locale();
     $templates = SS_TemplateLoader::instance()->getManifest()->getTemplates();
     foreach ($templates as $t) {
         $isOverwritten = false;
         // Emails in mysite/email are not properly marked as emails
         if (isset($t['mysite']) && isset($t['mysite']['email'])) {
             $t['email'] = $t['mysite']['email'];
         }
         // Should be in the /email folder
         if (!isset($t['email'])) {
             continue;
         }
         $filePath = $t['email'];
         $fileName = basename($filePath, '.ss');
         // Should end with *Email
         if (!preg_match('/Email$/', $fileName)) {
             continue;
         }
         $relativeFilePath = str_replace(Director::baseFolder(), '', $filePath);
         $relativeFilePathParts = explode('/', trim($relativeFilePath, '/'));
         // Group by module
         $module = array_shift($relativeFilePathParts);
         // Ignore some modules
         if (in_array($module, $ignoredModules)) {
             continue;
         }
         array_shift($relativeFilePathParts);
         // remove /templates part
         $templateName = str_replace('.ss', '', implode('/', $relativeFilePathParts));
         $templateTitle = basename($templateName);
         // Create a default code from template name
         $code = strtolower(preg_replace('/([a-zA-Z])(?=[A-Z])/', '$1-', $fileName));
         $code = preg_replace('/-email$/', '', $code);
         if (!empty($templatesToImport) && !in_array($code, $templatesToImport)) {
             echo "<div style='color:blue'>Template with code '{$code}' was ignored.</div>";
             continue;
         }
         $emailTemplate = EmailTemplate::get()->filter('Code', $code)->first();
         if (!$overwrite && $emailTemplate) {
             echo "<div style='color:blue'>Template with code '{$code}' already exists.</div>";
             continue;
         }
         // Create a default title from code
         $title = explode('-', $code);
         $title = array_map(function ($item) {
             return ucfirst($item);
         }, $title);
         $title = implode(' ', $title);
         // Get content of the email
         $content = file_get_contents($filePath);
         // Analyze content to find incompatibilities
         $errors = array();
         if (strpos($content, '<% with') !== false) {
             $errors[] = 'Replace "with" blocks by plain calls to the variable';
         }
         if (strpos($content, '<% if') !== false) {
             $errors[] = 'If/else logic is not supported. Please create one template by use case or abstract logic into the model';
         }
         if (strpos($content, '<% loop') !== false) {
             $errors[] = 'Loops are not supported. Please create a helper method on the model to render the loop';
         }
         if (strpos($content, '<% sprintf') !== false) {
             $errors[] = 'You should not use sprintf to escape content, please use plain _t calls';
         }
         if (!empty($errors)) {
             echo "<div style='color:red'>Invalid syntax was found in '{$relativeFilePath}'. Please fix these errors before importing the template<ul>";
             foreach ($errors as $error) {
                 echo '<li>' . $error . '</li>';
             }
             echo '</ul></div>';
             continue;
         }
         // Parse language
         $collector = new i18nTextCollector();
         $entities = $collector->collectFromTemplate($content, $fileName, $module);
         $translationTable = array();
         foreach ($entities as $entity => $data) {
             if ($locales) {
                 foreach ($locales as $locale) {
                     i18n::set_locale($locale);
                     if (!isset($translationTable[$entity])) {
                         $translationTable[$entity] = array();
                     }
                     $translationTable[$entity][$locale] = i18n::_t($entity);
                 }
                 i18n::set_locale($defaultLocale);
             } else {
                 $translationTable[$entity] = array($defaultLocale => i18n::_t($entity));
             }
         }
         $contentLocale = array();
         foreach ($locales as $locale) {
             $contentLocale[$locale] = $content;
         }
         foreach ($translationTable as $entity => $translationData) {
             $escapedEntity = str_replace('.', '\\.', $entity);
             $baseTranslation = null;
             foreach ($translationData as $locale => $translation) {
                 if (!$baseTranslation && $translation) {
                     $baseTranslation = $translation;
                 }
                 if (!$translation) {
                     $translation = $baseTranslation;
                 }
                 // This regex should match old and new style
                 $count = 0;
                 $contentLocale[$locale] = preg_replace("/<%(t | _t\\(')" . $escapedEntity . "( |').*?%>/ums", $translation, $contentLocale[$locale], -1, $count);
                 if (!$count) {
                     throw new Exception("Failed to replace {$escapedEntity} with translation {$translation}");
                 }
             }
         }
         if (!$emailTemplate) {
             $emailTemplate = new EmailTemplate();
         } else {
             $isOverwritten = true;
         }
         // Scan for extra models based on convention
         preg_match_all('/\\$([a-zA-Z]+)\\./ms', $contentLocale[$defaultLocale], $matches);
         $extraModels = array();
         if (!empty($matches) && !empty($matches[1])) {
             $arr = array_unique($matches[1]);
             foreach ($arr as $n) {
                 if (strtolower($n) === 'siteconfig') {
                     continue;
                 }
                 if (class_exists($n)) {
                     $extraModels[$n] = $n;
                 }
             }
         }
         // Apply content to email
         $this->assignContent($emailTemplate, $contentLocale[$defaultLocale]);
         if (!empty($locales)) {
             foreach ($locales as $locale) {
                 $this->assignContent($emailTemplate, $contentLocale[$locale], $locale);
             }
         }
         // Title
         $emailTemplate->Title = $title;
         if (!empty($locales)) {
             // By convention, we store the translation under NameOfTheTemplateEmail.SUBJECT
             foreach ($locales as $locale) {
                 i18n::set_locale($locale);
                 $localeField = 'Title_' . $locale;
                 $entity = $templateTitle . '.SUBJECT';
                 $translation = i18n::_t($entity);
                 if (!$translation) {
                     $translation = $title;
                 }
                 $emailTemplate->{$localeField} = $translation;
                 if (strpos($translation, '%s') !== false) {
                     echo '<div style="color:red">There is a %s in the title that should be replaced in locale ' . $locale . '!</div>';
                 }
                 if ($locale == $defaultLocale) {
                     $emailTemplate->Title = $translation;
                 }
             }
             i18n::set_locale($defaultLocale);
         }
         // Other properties
         $emailTemplate->Code = $code;
         $emailTemplate->Category = $module;
         $emailTemplate->setExtraModelsAsArray($extraModels);
         $emailTemplate->write();
         $subsiteImport = '';
         // Loop through subsites
         if ($importToSubsite) {
             $subsiteImport .= ' => Main site and subsites';
             Subsite::$disable_subsite_filter = true;
             foreach ($subsites as $subsiteID => $subsiteTitle) {
                 $subsiteEmailTemplate = EmailTemplate::get()->filter(array('Code' => $code, 'SubsiteID' => $subsiteID))->first();
                 $emailTemplateCopy = $emailTemplate;
                 $emailTemplateCopy->SubsiteID = $subsiteID;
                 if ($subsiteEmailTemplate) {
                     $emailTemplateCopy->ID = $subsiteEmailTemplate->ID;
                 } else {
                     $emailTemplateCopy->ID = 0;
                     // New
                 }
                 $emailTemplateCopy->write();
             }
         }
         if ($isOverwritten) {
             echo "<div style='color:orange'>Overwrote {$emailTemplate->Code}{$subsiteImport}</div>";
         } else {
             echo "<div style='color:green'>Imported {$emailTemplate->Code}{$subsiteImport}</div>";
         }
     }
 }
 public function updateCMSFields(FieldList $fields)
 {
     // get all fields to translate and remove
     $translated = $this->getTranslatedTables();
     foreach ($translated as $table => $translatedFields) {
         foreach ($translatedFields as $translatedField) {
             // Find field matching this translated field
             // If the translated field has an ID suffix also check for the non-suffixed version
             // E.g. UploadField()
             $field = $fields->dataFieldByName($translatedField);
             if (!$field && preg_match('/^(?<field>\\w+)ID$/', $translatedField, $matches)) {
                 $field = $fields->dataFieldByName($matches['field']);
             }
             // Highlight any translated field
             if ($field && !$field->hasClass('LocalisedField')) {
                 // Add a language indicator next to the fluent icon
                 $locale = Fluent::current_locale();
                 $title = $field->Title();
                 $field->setTitle('<span class="fluent-locale-label">' . strtok($locale, '_') . '</span>' . $title);
                 $field->addExtraClass('LocalisedField');
             }
             // Remove translation DBField from automatic scaffolded fields
             foreach (Fluent::locales() as $locale) {
                 $fieldName = Fluent::db_field_for_locale($translatedField, $locale);
                 $fields->removeByName($fieldName, true);
             }
         }
     }
 }
 /**
  * Determine the baseurl within a specified $locale.
  *
  * @param string $locale Locale, or null to use current locale
  * @return string
  */
 public static function locale_baseurl($locale = null)
 {
     if (empty($locale)) {
         $locale = Fluent::current_locale();
     }
     // Build domain-specific base url
     $base = Director::baseURL();
     if ($domain = Fluent::domain_for_locale($locale)) {
         $base = Controller::join_links(Director::protocol() . $domain, $base);
     }
     // Don't append locale to home page for default locale
     if ($locale === self::default_locale()) {
         return $base;
     }
     // Append locale otherwise
     return Controller::join_links($base, self::alias($locale), '/');
 }
 /**
  * Add 'Hidden' flag to the SiteTree object if the page is not present in this locale
  *
  * @param array $flags
  */
 public function updateStatusFlags(&$flags)
 {
     if (!$this->owner->{Fluent::db_field_for_locale("LocaleFilter", Fluent::current_locale())}) {
         $flags['fluenthidden'] = array('text' => _t('Fluent.BadgeHiddenShort', 'Hidden'), 'title' => _t('Fluent.BadgeHiddenHelp', 'Page is hidden in this locale'));
     }
 }
 /**
  * 
  * Return a MenuTitle depending on if we have the Fluent module enabled, and the
  * current selected locale.
  * 
  * It is also obviously contingent on each of the MenuTitle_<locale> fields 
  * having been configured correctly.
  * 
  * This method obviously _only_ deals with the MenuTitle_<locale> field. It is
  * therefore not at all DRY in the sense that there is no answer to the following
  * question: What do we do for other properties-as-fields, configured and 
  * translated via Fluent? 
  * 
  * @return string
  */
 public function MenuTitle()
 {
     if ($this->hasFluent()) {
         $localeCurrent = Fluent::current_locale();
         $fieldCurrent = 'MenuTitle_' . $localeCurrent;
         if (isset($this->{$fieldCurrent}) && ($title = $this->{$fieldCurrent})) {
             return $title;
         }
     }
     return $this->MenuTitle;
 }
 /**
  * Adds a UI message to indicate whether you're editing in the default locale or not
  *
  * @param  FieldList $fields
  * @return $this
  */
 protected function addLocaleIndicatorMessage(FieldList $fields)
 {
     if (Fluent::config()->disable_current_locale_message) {
         return $this;
     }
     // If the field is already present, don't add it a second time
     if ($fields->fieldByName('CurrentLocaleMessage')) {
         return $this;
     }
     $localeNames = Fluent::locale_names();
     $isDefaultLocale = Fluent::default_locale() === Fluent::current_locale();
     $messageClass = $isDefaultLocale ? 'good' : 'notice';
     $message = $isDefaultLocale ? _t('Fluent.DefaultLocale', 'This is the default locale') : _t('Fluent.DefaultLocaleIs', 'The default locale is') . ' ' . $localeNames[Fluent::default_locale()];
     $fields->unshift(LiteralField::create('CurrentLocaleMessage', sprintf('<p class="message %s">' . _t('Fluent.EditingIn', 'Please note: You are editing in') . ' %s. %s.</p>', $messageClass, $localeNames[Fluent::current_locale()], $message)));
     return $this;
 }
 public function updateCMSFields(FieldList $fields)
 {
     // get all fields to translate and remove
     $translated = $this->getTranslatedTables();
     foreach ($translated as $table => $translatedFields) {
         foreach ($translatedFields as $translatedField) {
             // Find field matching this translated field
             // If the translated field has an ID suffix also check for the non-suffixed version
             // E.g. UploadField()
             $field = $fields->dataFieldByName($translatedField);
             if (!$field && preg_match('/^(?<field>\\w+)ID$/', $translatedField, $matches)) {
                 $field = $fields->dataFieldByName($matches['field']);
             }
             // Highlight any translated field
             if ($field) {
                 $field->addExtraClass('LocalisedField');
             }
             // Remove translation DBField from automatic scaffolded fields
             foreach (Fluent::locales() as $locale) {
                 $fieldName = Fluent::db_field_for_locale($translatedField, $locale);
                 $fields->removeByName($fieldName, true);
             }
         }
     }
 }
 public function onBeforeInit()
 {
     Fluent::install_locale();
 }
 /**
  * Resets all translated fields to their value in the default locale
  */
 public function resetTranslations()
 {
     $translated = $this->getTranslatedTables();
     foreach ($translated as $table => $fields) {
         foreach ($fields as $field) {
             $defaultField = Fluent::db_field_for_locale($field, Fluent::default_locale());
             $defaultValue = $this->owner->{$defaultField};
             foreach (Fluent::locales() as $locale) {
                 if ($locale === Fluent::default_locale()) {
                     continue;
                 }
                 $localeField = Fluent::db_field_for_locale($field, $locale);
                 $originalValue = $this->owner->{$localeField};
                 $this->owner->{$localeField} = $defaultValue;
                 // If these values differ, but a change isn't detected, then force a change
                 if ($this->owner->exists() && $originalValue != $defaultValue && !$this->owner->isChanged($field)) {
                     $this->owner->forceChange();
                 }
                 $this->owner->write();
             }
         }
     }
 }
Example #20
0
 /**
  * Tests adding an invalid validator.
  */
 public function testAddInvalidValidator()
 {
     $this->expectException(\Jyxo\Input\Exception::class);
     $input = new Fluent();
     $input->validate('foo');
 }
 /**
  * Test fluent setters.
  */
 public function testFluentSetters()
 {
     $config = new Config(array('inputFile' => null, 'outputDir' => null));
     $complexType = new ComplexType($config, 'Fluent');
     $complexType->addMember('string', 'attribute', true);
     $this->generateClass($complexType);
     // When calling a setter the returned value should be the same as the
     // object where the setter was called.
     $object = new \Fluent();
     $returnValue = $object->setAttribute('value');
     $this->assertEquals($object, $returnValue);
     // The setter should also have its own class as its return type.
     $class = new \ReflectionClass($object);
     $this->assertMethodHasReturnType($class->getMethod('setAttribute'), $class->getName());
 }
 public function run($request)
 {
     echo 'Run with ?clear=1 to clear empty database before running the task<br/>';
     echo 'Run with ?overwrite=soft|hard to overwrite templates that exists in the cms. Soft will replace template if not modified by the user, hard will replace template even if modified by user.<br/>';
     echo 'Run with ?templates=xxx,yyy to specify which template should be imported<br/>';
     echo 'Run with ?subsite=all|subsiteID to create email templates in all subsites (including main site) or only in the chosen subsite (if a subsite is active, it will be used by default).<br/>';
     echo 'Run with ?locales=fr,en to choose which locale to import.<br/>';
     echo '<strong>Remember to flush the templates/translations if needed</strong><br/>';
     echo '<hr/>';
     $overwrite = $request->getVar('overwrite');
     $clear = $request->getVar('clear');
     $templatesToImport = $request->getVar('templates');
     $importToSubsite = $request->getVar('subsite');
     $chosenLocales = $request->getVar('locales');
     // Normalize argument
     if ($overwrite && $overwrite != 'soft' && $overwrite != 'hard') {
         $overwrite = 'soft';
     }
     $subsites = array();
     if ($importToSubsite == 'all') {
         $subsites = Subsite::get()->map();
     } else {
         if (is_numeric($importToSubsite)) {
             $subsites = array($importToSubsite => Subsite::get()->byID($importToSubsite)->Title);
         }
     }
     if (class_exists('Subsite') && Subsite::currentSubsiteID()) {
         DB::alteration_message("Importing to current subsite. Run from main site to import other subsites at once.", "created");
         $subsites = array();
     }
     if (!empty($subsites)) {
         DB::alteration_message("Importing to subsites : " . implode(',', array_values($subsites)), "created");
     }
     if ($templatesToImport) {
         $templatesToImport = explode(',', $templatesToImport);
     }
     if ($clear == 1) {
         DB::alteration_message("Clear all email templates", "created");
         $emailTemplates = EmailTemplate::get();
         foreach ($emailTemplates as $emailTemplate) {
             $emailTemplate->delete();
         }
     }
     $emailTemplateSingl = singleton('EmailTemplate');
     $ignoredModules = self::config()->ignored_modules;
     if (!is_array($ignoredModules)) {
         $ignoredModules = array();
     }
     $locales = null;
     if (class_exists('Fluent') && Fluent::locale_names()) {
         if ($emailTemplateSingl->hasExtension('FluentExtension')) {
             $locales = array_keys(Fluent::locale_names());
             if ($chosenLocales) {
                 $arr = explode(',', $chosenLocales);
                 $locales = array();
                 foreach ($arr as $a) {
                     if (strlen($a) == 2) {
                         $a = i18n::get_locale_from_lang($a);
                     }
                     $locales[] = $a;
                 }
             }
         }
     }
     $defaultLocale = i18n::get_locale();
     $templates = SS_TemplateLoader::instance()->getManifest()->getTemplates();
     foreach ($templates as $t) {
         $isOverwritten = false;
         // Emails in mysite/email are not properly marked as emails
         if (isset($t['mysite']) && isset($t['mysite']['email'])) {
             $t['email'] = $t['mysite']['email'];
         }
         // Should be in the /email folder
         if (!isset($t['email'])) {
             continue;
         }
         $filePath = $t['email'];
         $fileName = basename($filePath, '.ss');
         // Should end with *Email
         if (!preg_match('/Email$/', $fileName)) {
             continue;
         }
         $relativeFilePath = str_replace(Director::baseFolder(), '', $filePath);
         $relativeFilePathParts = explode('/', trim($relativeFilePath, '/'));
         // Group by module
         $module = array_shift($relativeFilePathParts);
         // Ignore some modules
         if (in_array($module, $ignoredModules)) {
             continue;
         }
         array_shift($relativeFilePathParts);
         // remove /templates part
         $templateName = str_replace('.ss', '', implode('/', $relativeFilePathParts));
         $templateTitle = basename($templateName);
         // Create a default code from template name
         $code = strtolower(preg_replace('/([a-zA-Z])(?=[A-Z])/', '$1-', $fileName));
         $code = preg_replace('/-email$/', '', $code);
         if (!empty($templatesToImport) && !in_array($code, $templatesToImport)) {
             DB::alteration_message("Template with code <b>{$code}</b> was ignored.", "repaired");
             continue;
         }
         $whereCode = array('Code' => $code);
         $emailTemplate = EmailTemplate::get()->filter($whereCode)->first();
         // Check if it has been modified or not
         $templateModified = false;
         if ($emailTemplate) {
             $templateModified = $emailTemplate->Created != $emailTemplate->LastEdited;
         }
         if (!$overwrite && $emailTemplate) {
             DB::alteration_message("Template with code <b>{$code}</b> already exists. Choose overwrite if you want to import again.", "repaired");
             continue;
         }
         if ($overwrite == 'soft' && $templateModified) {
             DB::alteration_message("Template with code <b>{$code}</b> has been modified by the user. Choose overwrite=hard to change.", "repaired");
             continue;
         }
         // Create a default title from code
         $title = explode('-', $code);
         $title = array_map(function ($item) {
             return ucfirst($item);
         }, $title);
         $title = implode(' ', $title);
         // Get content of the email
         $content = file_get_contents($filePath);
         // Analyze content to find incompatibilities
         $errors = array();
         if (strpos($content, '<% with') !== false) {
             $errors[] = 'Replace "with" blocks by plain calls to the variable';
         }
         if (strpos($content, '<% if') !== false) {
             $errors[] = 'If/else logic is not supported. Please create one template by use case or abstract logic into the model';
         }
         if (strpos($content, '<% loop') !== false) {
             $errors[] = 'Loops are not supported. Please create a helper method on the model to render the loop';
         }
         if (strpos($content, '<% sprintf') !== false) {
             $errors[] = 'You should not use sprintf to escape content, please use plain _t calls';
         }
         if (!empty($errors)) {
             echo "<div style='color:red'>Invalid syntax was found in '{$relativeFilePath}'. Please fix these errors before importing the template<ul>";
             foreach ($errors as $error) {
                 echo '<li>' . $error . '</li>';
             }
             echo '</ul></div>';
             continue;
         }
         // Parse language
         $collector = new i18nTextCollector();
         $entities = $collector->collectFromTemplate($content, $fileName, $module);
         $translationTable = array();
         foreach ($entities as $entity => $data) {
             if ($locales) {
                 foreach ($locales as $locale) {
                     i18n::set_locale($locale);
                     if (!isset($translationTable[$entity])) {
                         $translationTable[$entity] = array();
                     }
                     $translationTable[$entity][$locale] = i18n::_t($entity);
                 }
                 i18n::set_locale($defaultLocale);
             } else {
                 $translationTable[$entity] = array($defaultLocale => i18n::_t($entity));
             }
         }
         $contentLocale = array();
         foreach ($locales as $locale) {
             $contentLocale[$locale] = $content;
         }
         foreach ($translationTable as $entity => $translationData) {
             $escapedEntity = str_replace('.', '\\.', $entity);
             $baseTranslation = null;
             foreach ($translationData as $locale => $translation) {
                 if (!$baseTranslation && $translation) {
                     $baseTranslation = $translation;
                 }
                 if (!$translation) {
                     $translation = $baseTranslation;
                 }
                 // This regex should match old and new style
                 $count = 0;
                 $contentLocale[$locale] = preg_replace("/<%(t | _t\\(')" . $escapedEntity . "( |').*?%>/ums", $translation, $contentLocale[$locale], -1, $count);
                 if (!$count) {
                     throw new Exception("Failed to replace {$escapedEntity} with translation {$translation}");
                 }
             }
         }
         if (!$emailTemplate) {
             $emailTemplate = new EmailTemplate();
         } else {
             $isOverwritten = true;
         }
         // Scan for extra models based on convention
         preg_match_all('/\\$([a-zA-Z]+)\\./ms', $contentLocale[$defaultLocale], $matches);
         $extraModels = array();
         if (!empty($matches) && !empty($matches[1])) {
             $arr = array_unique($matches[1]);
             foreach ($arr as $n) {
                 if (strtolower($n) === 'siteconfig') {
                     continue;
                 }
                 if (class_exists($n)) {
                     $extraModels[$n] = $n;
                 }
             }
         }
         // Apply content to email
         $this->assignContent($emailTemplate, $contentLocale[$defaultLocale]);
         if (!empty($locales)) {
             foreach ($locales as $locale) {
                 $this->assignContent($emailTemplate, $contentLocale[$locale], $locale);
             }
         }
         // Title
         $emailTemplate->Title = $title;
         if (!empty($locales)) {
             // By convention, we store the translation under NameOfTheTemplateEmail.SUBJECT
             foreach ($locales as $locale) {
                 i18n::set_locale($locale);
                 $localeField = 'Title_' . $locale;
                 $entity = $templateTitle . '.SUBJECT';
                 $translation = i18n::_t($entity);
                 if (!$translation) {
                     $translation = $title;
                     DB::alteration_message("No title found in {$locale} for {$title}. You should define {$templateTitle}.SUBJECT", "error");
                 }
                 $emailTemplate->{$localeField} = $translation;
                 if (strpos($translation, '%s') !== false) {
                     echo '<div style="color:red">There is a %s in the title that should be replaced in locale ' . $locale . '!</div>';
                 }
                 if ($locale == $defaultLocale) {
                     $emailTemplate->Title = $translation;
                 }
             }
             i18n::set_locale($defaultLocale);
         }
         // Other properties
         $emailTemplate->Code = $code;
         $emailTemplate->Category = $module;
         if (class_exists('Subsite') && Subsite::currentSubsiteID()) {
             $emailTemplate->SubsiteID = Subsite::currentSubsiteID();
         }
         $emailTemplate->setExtraModelsAsArray($extraModels);
         // Write to main site or current subsite
         $emailTemplate->write();
         $this->resetLastEditedDate($emailTemplate->ID);
         // Loop through subsites
         if (!empty($importToSubsite)) {
             Subsite::$disable_subsite_filter = true;
             foreach ($subsites as $subsiteID => $subsiteTitle) {
                 $whereCode['SubsiteID'] = $subsiteID;
                 $subsiteEmailTemplate = EmailTemplate::get()->filter($whereCode)->first();
                 $emailTemplateCopy = $emailTemplate;
                 $emailTemplateCopy->SubsiteID = $subsiteID;
                 if ($subsiteEmailTemplate) {
                     $emailTemplateCopy->ID = $subsiteEmailTemplate->ID;
                 } else {
                     $emailTemplateCopy->ID = 0;
                     // New
                 }
                 $emailTemplateCopy->write();
                 $this->resetLastEditedDate($emailTemplateCopy->ID);
             }
         }
         if ($isOverwritten) {
             DB::alteration_message("Overwrote <b>{$emailTemplate->Code}</b>", "created");
         } else {
             DB::alteration_message("Imported <b>{$emailTemplate->Code}</b>", "created");
         }
     }
 }
Example #23
0
 /**
  * Sets whether to force "is_frontend" to return true or false. This can be used for situations where the
  * frontend controllers are not involved, e.g. API modules, unit testing or retrieving data programmatically.
  *
  * @param boolean $force
  */
 public static function set_force_is_frontend($force = true)
 {
     self::$force_is_frontend = $force;
 }
 /**
  * Rewrites the WHERE fragment of a query
  *
  * @param string $class
  * @param array $translatedColumns Translated columns
  * @param SQLQUery $query
  * @param string $keywords SQL escaped keywords
  * @param string $keywordsHTML HTML escaped keywords
  */
 public function augmentFilter($class, $translatedColumns, SQLQuery $query, $keywords, $keywordsHTML, $booleanMode)
 {
     // Augment the search section
     $locale = Fluent::current_locale();
     $wherePattern = self::$where_replacements[$class];
     $translatedPattern = $wherePattern;
     $searchColumns = self::$search_columns[$class];
     foreach (array_intersect($searchColumns, $translatedColumns) as $column) {
         $replacement = Fluent::db_field_for_locale($column, $locale);
         $translatedPattern = preg_replace('/\\b' . preg_quote($column) . '\\b/', $replacement, $translatedPattern);
     }
     // If no fields were translated, then don't modify
     if ($translatedPattern === $wherePattern) {
         return;
     }
     // Inject keywords into patterns
     $search = array('/\\$keywords/i', '/\\$htmlEntityKeywords/i', '/\\$boolean/i');
     $replace = array($keywords, $keywordsHTML, $booleanMode ? 'IN BOOLEAN MODE' : '');
     $whereOriginal = preg_replace($search, $replace, $wherePattern);
     $whereTranslated = preg_replace($search, $replace, $translatedPattern);
     $where = $query->getWhere();
     $newWhere = array();
     foreach ($query->getWhere() as $where) {
         // Remove excessive whitespace which breaks string replacement
         $where = preg_replace('/\\s+/im', ' ', $where);
         $whereOriginal = preg_replace('/\\s+/im', ' ', $whereOriginal);
         $newWhere[] = str_replace($whereOriginal, "{$whereOriginal} + {$whereTranslated}", $where);
     }
     $query->setWhere($newWhere);
 }
Example #25
0
 /**
  * Tests adding an invalid validator.
  */
 public function testAddInvalidValidator()
 {
     $this->setExpectedException('\\Jyxo\\Input\\Exception');
     $input = new Fluent();
     $input->validate('foo');
 }
    public function run($request)
    {
        // Extend time limit
        set_time_limit(100000);
        // we may need some proivileges for this to work
        // without this, running under sake is a problem
        // maybe sake could take care of it ...
        Security::findAnAdministrator()->login();
        $this->checkInstalled();
        $this->withTransaction(function ($task) {
            Versioned::reading_stage('Stage');
            $classes = $task->fluentClasses();
            $tables = DB::tableList();
            $deleteQueue = array();
            foreach ($classes as $class) {
                // Ensure that a translationgroup table exists for this class
                $groupTable = strtolower($class . "_translationgroups");
                if (isset($tables[$groupTable])) {
                    $groupTable = $tables[$groupTable];
                } else {
                    Debug::message("Ignoring class without _translationgroups table {$class}", false);
                    continue;
                }
                // Disable filter
                if ($class::has_extension('FluentFilteredExtension')) {
                    $class::remove_extension('FluentFilteredExtension');
                }
                // Select all instances of this class in the default locale
                $instances = DataObject::get($class, sprintf('"Locale" = \'%s\'', Convert::raw2sql(Fluent::default_locale())));
                foreach ($instances as $instance) {
                    $isPublished = false;
                    if ($instance->hasMethod('isPublished')) {
                        $isPublished = $instance->isPublished();
                    }
                    if ($instance->ObsoleteClassName) {
                        Debug::message("Skipping {$instance->ClassName} with ID {$instanceID} because it from an obsolete class", false);
                        continue;
                    }
                    $instanceID = $instance->ID;
                    $translatedFields = $task->getTranslatedFields($instance->ClassName);
                    Debug::message("Updating {$instance->ClassName} {$instance->MenuTitle} ({$instanceID})", false);
                    $changed = false;
                    // Select all translations for this
                    $translatedItems = DataObject::get($class, sprintf('"Locale" != \'%1$s\' AND "ID" IN (
							SELECT "OriginalID" FROM "%2$s" WHERE "TranslationGroupID" IN (
								SELECT "TranslationGroupID" FROM "%2$s" WHERE "OriginalID" = %3$d
							)
						)', Convert::raw2sql(Fluent::default_locale()), $groupTable, $instanceID));
                    foreach ($translatedItems as $translatedItem) {
                        $locale = DB::query(sprintf('SELECT "Locale" FROM "%s" WHERE "ID" = %d', $class, $translatedItem->ID))->value();
                        // since we are going to delete the stuff
                        // anyway, no need bothering validating it
                        DataObject::config()->validation_enabled = false;
                        // Unpublish and delete translated record
                        if ($translatedItem->hasMethod('doUnpublish')) {
                            Debug::message("  --  Unpublishing {$locale}", false);
                            if ($translatedItem->doUnpublish() === false) {
                                throw new ConvertTranslatableException("Failed to unpublish");
                            }
                        }
                        Debug::message("  --  Adding {$translatedItem->ID} ({$locale})", false);
                        foreach ($translatedFields as $field) {
                            $trField = Fluent::db_field_for_locale($field, $locale);
                            if ($translatedItem->{$field}) {
                                Debug::message("     --  Adding {$trField}", false);
                                $instance->{$trField} = $translatedItem->{$field};
                                $changed = true;
                            }
                        }
                        // for some reason, deleting items here has disruptive effects
                        // as too much stuff gets removed, so lets wait with this until the end of the migration
                        $deleteQueue[] = $translatedItem;
                    }
                    if ($changed) {
                        if (!$isPublished) {
                            $instance->write();
                        } elseif ($instance->doPublish() === false) {
                            Debug::message("  --  Publishing FAILED", false);
                            throw new ConvertTranslatableException("Failed to publish");
                        } else {
                            Debug::message("  --  Published", false);
                        }
                    }
                }
            }
            foreach ($deleteQueue as $delItem) {
                Debug::message("  --  Removing {$delItem->ID}", false);
                $delItem->delete();
            }
        });
    }
 /**
  * If only one locale is active
  * 
  * @return string|boolean The active locale or false
  */
 public function HasOnlyOneLocale()
 {
     $list = $this->owner->ActiveLocales;
     if (!$list) {
         $list = implode(',', array_keys(Fluent::locale_names()));
     }
     $list = trim($list, ',');
     if ($list && strpos($list, ',') === false) {
         return $list;
     }
     return false;
 }
 public function Link()
 {
     return Controller::join_links(Director::baseURL(), Fluent::current_locale(), 'link', '/');
 }
Example #29
0
 /**
  * Compile a primary key command.
  *
  * @param  Schema_Blueprint $blueprint
  * @param  Fluent           $command
  * @return string
  */
 public function compile_primary(Schema_Blueprint $blueprint, Fluent $command)
 {
     $command->name(NULL);
     return $this->_compile_key($blueprint, $command, 'primary key');
 }
Example #30
0
 public function __construct(array $attributes = [])
 {
     parent::__construct($attributes);
     $this->syncOriginal();
 }