security update core+modules
This commit is contained in:
@@ -28,7 +28,7 @@ class i18n_string_object {
|
||||
// Properties from metadata
|
||||
public $title;
|
||||
// Array of translations to multiple languages
|
||||
public $translations;
|
||||
public $translations = array();
|
||||
// Textgroup object
|
||||
protected $_textgroup;
|
||||
|
||||
@@ -39,7 +39,49 @@ class i18n_string_object {
|
||||
if ($data) {
|
||||
$this->set_properties($data);
|
||||
}
|
||||
// Attempt to re-build the data from the persistent cache.
|
||||
$this->rebuild_from_cache($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rebuild the object data based on the persistent cache.
|
||||
*
|
||||
* Since the textgroup defines if a string is cacheable or not the caching
|
||||
* of the string objects happens in the textgroup handler itself.
|
||||
*
|
||||
* @see i18n_string_textgroup_cached::__destruct()
|
||||
*/
|
||||
protected function rebuild_from_cache($data = NULL) {
|
||||
// Check if we've the required information to repopulate the cache and do so
|
||||
// if possible.
|
||||
$meta_data_exist = isset($this->textgroup) && isset($this->type) && isset($this->objectid) && isset($this->property);
|
||||
if ($meta_data_exist && ($cache = cache_get($this->get_cid())) && !empty($cache->data)) {
|
||||
// Re-spawn the cached data.
|
||||
// @TODO do we need a array_diff to ensure we don't overwrite the data
|
||||
// provided by the $data parameter?
|
||||
$this->set_properties($cache->data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset cache, needed for tests.
|
||||
*/
|
||||
public function cache_reset() {
|
||||
$this->translations = array();
|
||||
// Ensure a possible persistent cache of this object is cleared too.
|
||||
cache_clear_all($this->get_cid(), 'cache', TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the caching id for this object.
|
||||
*
|
||||
* @return string
|
||||
* The caching id.
|
||||
*/
|
||||
public function get_cid() {
|
||||
return 'i18n:string:obj:' . $this->get_name();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get message parameters from context and string.
|
||||
*/
|
||||
@@ -63,6 +105,10 @@ class i18n_string_object {
|
||||
$this->objectkey = (int)$this->objectid;
|
||||
// Remaining elements glued again with ':'
|
||||
$this->property = $parts ? implode(':', $parts) : '';
|
||||
|
||||
// Attempt to re-build the other data from the persistent cache.
|
||||
$this->rebuild_from_cache();
|
||||
|
||||
return $this;
|
||||
}
|
||||
/**
|
||||
@@ -100,13 +146,14 @@ class i18n_string_object {
|
||||
if (isset($string['format'])) {
|
||||
$this->format = $string['format'];
|
||||
}
|
||||
if (isset($string['title'])) {
|
||||
$this->title = $string['title'];
|
||||
}
|
||||
}
|
||||
else {
|
||||
$this->string = $string;
|
||||
}
|
||||
if (isset($string['title'])) {
|
||||
$this->title = $string['title'];
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
/**
|
||||
@@ -279,9 +326,9 @@ class i18n_string_textgroup_default {
|
||||
// Debug flag, set to true to print out more information.
|
||||
public $debug;
|
||||
// Cached or preloaded string objects
|
||||
public $strings;
|
||||
public $strings = array();
|
||||
// Multiple translations search map
|
||||
protected $cache_multiple;
|
||||
protected $cache_multiple = array();
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
@@ -400,8 +447,13 @@ class i18n_string_textgroup_default {
|
||||
/**
|
||||
* Filter array of strings
|
||||
*
|
||||
* @param $filter
|
||||
* @param array $string_list
|
||||
* Array of strings to be filtered.
|
||||
* @param array $filter
|
||||
* Array of name value conditions.
|
||||
*
|
||||
* @return array
|
||||
* Strings from $string_list that match the filter conditions.
|
||||
*/
|
||||
protected static function string_filter($string_list, $filter) {
|
||||
// Remove 'language' and '*' conditions.
|
||||
@@ -566,7 +618,11 @@ class i18n_string_textgroup_default {
|
||||
public function cache_reset() {
|
||||
$this->strings = array();
|
||||
$this->string_format = array();
|
||||
$this->translations = array();
|
||||
|
||||
// Reset the persistent caches.
|
||||
cache_clear_all('i18n:string:tgroup:' . $this->textgroup , 'cache', TRUE);
|
||||
// Reset the complete string object cache too.
|
||||
cache_clear_all('i18n:string:obj:', 'cache', TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -613,7 +669,7 @@ class i18n_string_textgroup_default {
|
||||
public static function load_translation($i18nstring, $langcode) {
|
||||
// Search the database using lid if we've got it or textgroup, context otherwise
|
||||
if (!empty($i18nstring->lid)) {
|
||||
// We've alreay got lid, we just need translation data
|
||||
// We've already got lid, we just need translation data
|
||||
$query = db_select('locales_target', 't');
|
||||
$query->condition('t.lid', $i18nstring->lid);
|
||||
}
|
||||
@@ -1188,6 +1244,10 @@ class i18n_string_object_wrapper extends i18n_object_wrapper {
|
||||
* Translate access (localize strings)
|
||||
*/
|
||||
protected function localize_access() {
|
||||
// We could check also whether the object has strings to translate:
|
||||
// && $this->get_strings(array('empty' => TRUE))
|
||||
// However it may be better to display the 'No available strings' message
|
||||
// for the user to have a clue of what's going on. See i18n_string_translate_page_object()
|
||||
return user_access('translate interface') && user_access('translate user-defined strings');
|
||||
}
|
||||
|
||||
@@ -1280,3 +1340,163 @@ class i18n_string_object_wrapper extends i18n_object_wrapper {
|
||||
return $this->textgroup()->load_strings(array('type' => $type, 'objectid' => $id));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Textgroup handler for i18n_string API which integrated persistent caching.
|
||||
*/
|
||||
class i18n_string_textgroup_cached extends i18n_string_textgroup_default {
|
||||
|
||||
/**
|
||||
* Defines the timeout for the persistent caching.
|
||||
* @var int
|
||||
*/
|
||||
public $caching_time = CACHE_TEMPORARY;
|
||||
|
||||
/**
|
||||
* Extends the existing constructor with a cache handling.
|
||||
*
|
||||
* @param string $textgroup
|
||||
* The name of this textgroup.
|
||||
*/
|
||||
public function __construct($textgroup) {
|
||||
parent::__construct($textgroup);
|
||||
// Fetch persistent caches, the persistent caches contain only metadata.
|
||||
// Those metadata are processed by the related cache_get() methods.
|
||||
foreach (array('cache_multiple', 'strings') as $caches_type) {
|
||||
if (($cache = cache_get('i18n:string:tgroup:' . $this->textgroup . ':' . $caches_type)) && !empty($cache->data)) {
|
||||
$this->{$caches_type} = $cache->data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class destructor.
|
||||
*
|
||||
* Updates the persistent caches for the next usage.
|
||||
* This function not only stores the data of the textgroup objects but also
|
||||
* of the string objects. That way we ensure that only cacheable string object
|
||||
* go into the persistent cache.
|
||||
*/
|
||||
public function __destruct() {
|
||||
// Reduce size to cache by removing NULL values.
|
||||
$this->strings = array_filter($this->strings);
|
||||
|
||||
|
||||
$strings_to_cache = array();
|
||||
// Store the persistent caches. We just store the metadata the translations
|
||||
// are stored by the string object itself. However storing the metadata
|
||||
// reduces the number of DB queries executed during runtime.
|
||||
$cache_data = array();
|
||||
foreach ($this->strings as $context => $i18n_string_object) {
|
||||
$cache_data[$context] = $context;
|
||||
$strings_to_cache[$context] = $i18n_string_object;
|
||||
}
|
||||
cache_set('i18n:string:tgroup:' . $this->textgroup . ':strings', $cache_data, 'cache', $this->caching_time);
|
||||
|
||||
$cache_data = array();
|
||||
foreach ($this->cache_multiple as $pattern => $strings) {
|
||||
foreach ($strings as $context => $i18n_string_object) {
|
||||
$cache_data[$pattern][$context] = $context;
|
||||
$strings_to_cache[$context] = $i18n_string_object;
|
||||
}
|
||||
}
|
||||
cache_set('i18n:string:tgroup:' . $this->textgroup . ':cache_multiple', $cache_data, 'cache', $this->caching_time);
|
||||
|
||||
// Cache the string objects related to this textgroup.
|
||||
// Store only the public visible data into the persistent cache.
|
||||
foreach ($strings_to_cache as $i18n_string_object) {
|
||||
// If this isn't an object it's an unprocessed cache item and doesn't need
|
||||
// to be stored again.
|
||||
if (is_object($i18n_string_object)) {
|
||||
cache_set($i18n_string_object->get_cid(), get_object_vars($i18n_string_object), 'cache', $this->caching_time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset cache, needed for tests.
|
||||
*
|
||||
* Takes care of the persistent caches.
|
||||
*/
|
||||
public function cache_reset() {
|
||||
// Reset the persistent caches.
|
||||
cache_clear_all('i18n:string:tgroup:' . $this->textgroup , 'cache', TRUE);
|
||||
// Reset the complete string object cache too. This will affect string
|
||||
// objects of other textgroups as well.
|
||||
cache_clear_all('i18n:string:obj:', 'cache', TRUE);
|
||||
|
||||
return parent::cache_reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get translation from cache.
|
||||
*
|
||||
* Extends the original handler with persistent caching.
|
||||
*
|
||||
* @param string $context
|
||||
* The context to look out for.
|
||||
* @return i18n_string_object|NULL
|
||||
* The string object if available or NULL otherwise.
|
||||
*/
|
||||
protected function cache_get($context) {
|
||||
if (isset($this->strings[$context])) {
|
||||
// If the cache contains a string re-build i18n_string_object.
|
||||
if (is_string($this->strings[$context])) {
|
||||
$i8n_string_object = new i18n_string_object(array('textgroup' => $this->textgroup));
|
||||
$i8n_string_object->set_context($context);
|
||||
$this->strings[$context] = $i8n_string_object;
|
||||
}
|
||||
// Now run the original handling.
|
||||
return parent::cache_get($context);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get strings from multiple cache.
|
||||
*
|
||||
* @param $context array
|
||||
* String context as array with language property at the end.
|
||||
*
|
||||
* @return mixed
|
||||
* Array of strings (may be empty) if we've got a cache hit.
|
||||
* Null otherwise.
|
||||
*/
|
||||
protected function multiple_cache_get($context) {
|
||||
// Ensure the values from the persistent cache are properly re-build.
|
||||
$cache_key = implode(':', $context);
|
||||
if (isset($this->cache_multiple[$cache_key])) {
|
||||
foreach ($this->cache_multiple[$cache_key] as $cached_context) {
|
||||
if (is_string($cached_context)) {
|
||||
$i8n_string_object = new i18n_string_object(array('textgroup' => $this->textgroup));
|
||||
$i8n_string_object->set_context($cached_context);
|
||||
$this->cache_multiple[$cache_key][$cached_context] = $i8n_string_object;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Now we try more generic keys. For instance, if we are searching 'term:1:*'
|
||||
// we may try too 'term:*:*' and filter out the results.
|
||||
foreach ($context as $key => $value) {
|
||||
if ($value != '*') {
|
||||
$try = array_merge($context, array($key => '*'));
|
||||
return $this->multiple_cache_get($try);
|
||||
}
|
||||
}
|
||||
}
|
||||
return parent::multiple_cache_get($context);
|
||||
}
|
||||
|
||||
public function string_update($i18nstring, $options = array()) {
|
||||
// Flush persistent cache.
|
||||
cache_clear_all($i18nstring->get_cid(), 'cache', TRUE);
|
||||
return parent::string_update($i18nstring, $options);
|
||||
}
|
||||
|
||||
public function string_remove($i18nstring, $options = array()) {
|
||||
// Flush persistent cache.
|
||||
cache_clear_all($i18nstring->get_cid(), 'cache', TRUE);
|
||||
return parent::string_remove($i18nstring, $options);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user