+ /**
+ * Flatten recursively an array
+ *
+ * @param array $data The data tree
+ * @param string|null $current The current prefix
+ * @param string $sep The key separator
+ * @param string $prefix The key prefix
+ * @param string $suffix The key suffix
+ * @return array The flattened data
+ */
+ public function flatten($data, $current = null, $sep = '.', $prefix = '', $suffix = '') {
+ //Init result
+ $ret = [];
+
+ //Look for data array
+ if (is_array($data)) {
+ //Iteare on each pair
+ foreach($data as $k => $v) {
+ //Merge flattened value in return array
+ $ret += $this->flatten($v, empty($current) ? $k : $current.$sep.$k, $sep, $prefix, $suffix);
+ }
+ //Look flat data
+ } else {
+ //Store data in flattened key
+ $ret[$prefix.$current.$suffix] = $data;
+ }
+
+ //Return result
+ return $ret;
+ }
+
+ /**
+ * Crypt and base64uri encode string
+ *
+ * @param string $data The data string
+ * @return string The hashed data
+ */
+ public function hash(string $data): string {
+ //Return hashed data
+ //XXX: we use hash_hmac with md5 hash
+ //XXX: crypt was dropped because it provided identical signature for string starting with same pattern
+ return str_replace(['+','/'], ['-','_'], base64_encode(hash_hmac('md5', $data, $this->secret, true)));
+ }
+
+ /**
+ * Serialize then short
+ *
+ * @param array $data The data array
+ * @return string The serialized and shorted data
+ */
+ public function serialize(array $data): string {
+ //Return shorted serialized data
+ return $this->short(serialize($data));
+ }
+
+ /**
+ * Short
+ *
+ * @param string $data The data string
+ * @return string The shorted data
+ */
+ public function short(string $data): string {