$table = self::getTableName();
$where = self::whereCache($group, $path, $componentID);
$rawData = CRM_Core_DAO::singleValueQuery("SELECT data FROM $table WHERE $where");
- $data = $rawData ? unserialize($rawData) : NULL;
+ $data = $rawData ? self::decode($rawData) : NULL;
self::$_cache[$argString] = $data;
$cache->set($argString, self::$_cache[$argString]);
$result = array();
while ($dao->fetch()) {
- $result[$dao->path] = unserialize($dao->data);
+ $result[$dao->path] = self::decode($dao->data);
}
$dao->free();
$where = self::whereCache($group, $path, $componentID);
$dataExists = CRM_Core_DAO::singleValueQuery("SELECT COUNT(*) FROM $table WHERE {$where}");
$now = date('Y-m-d H:i:s'); // FIXME - Use SQL NOW() or CRM_Utils_Time?
- $dataSerialized = serialize($data);
+ $dataSerialized = self::encode($data);
// This table has a wonky index, so we cannot use REPLACE or
// "INSERT ... ON DUPE". Instead, use SELECT+(INSERT|UPDATE).
$argString = "CRM_CT_{$group}_{$path}_{$componentID}";
$cache = CRM_Utils_Cache::singleton();
- $data = unserialize($dataSerialized);
+ $data = self::decode($dataSerialized);
self::$_cache[$argString] = $data;
$cache->set($argString, $data);
}
}
+ /**
+ * (Quasi-private) Encode an object/array/string/int as a string.
+ *
+ * @param $mixed
+ * @return string
+ */
+ public static function encode($mixed) {
+ return base64_encode(serialize($mixed));
+ }
+
+ /**
+ * (Quasi-private) Decode an object/array/string/int from a string.
+ *
+ * @param $string
+ * @return mixed
+ */
+ public static function decode($string) {
+ // Upgrade support -- old records (serialize) always have this punctuation,
+ // and new records (base64) never do.
+ if (strpos($string, ':') !== FALSE || strpos($string, ';') !== FALSE) {
+ return unserialize($string);
+ }
+ else {
+ return unserialize(base64_decode($string));
+ }
+ }
+
/**
* Compose a SQL WHERE clause for the cache.
*
*/
class CRM_Core_BAO_CacheTest extends CiviUnitTestCase {
+ public function testMultiVersionDecode() {
+ $encoders = ['serialize', ['CRM_Core_BAO_Cache', 'encode']];
+ $values = [NULL, 0, 1, TRUE, FALSE, [], ['abcd'], 'ab;cd', new stdClass()];
+ foreach ($encoders as $encoder) {
+ foreach ($values as $value) {
+ $encoded = $encoder($value);
+ $decoded = CRM_Core_BAO_Cache::decode($encoded);
+ $this->assertEquals($value, $decoded, "Failure encoding/decoding value " . var_export($value, 1) . ' with ' . var_export($encoder, 1));
+ }
+ }
+ }
+
public function exampleValues() {
$binary = '';
for ($i = 0; $i < 256; $i++) {