/**
  * Generate OKAPI changelog entries. This method will call $feeder_method OKAPI
  * service with the following parameters: array($feeder_keys_param => implode('|', $key_values),
  * 'fields' => $fields). Then it will generate the changelog, based on the result.
  * This looks pretty much the same for various object types, that's why it's here.
  *
  * If $use_cache is true, then all the dictionaries from $feeder_method will be also
  * kept in OKAPI cache, for future comparison.
  *
  * In normal mode, update the changelog and don't return anything.
  * In fulldump mode, return the generated changelog entries *instead* of
  * updating it.
  */
 private static function generate_changelog_entries($feeder_method, $object_type, $feeder_keys_param, $key_name, $key_values, $fields, $fulldump_mode, $use_cache, $cache_timeout = 86400)
 {
     # Retrieve the previous versions of all objects from OKAPI cache.
     if ($use_cache) {
         $cache_keys1 = array();
         $cache_keys2 = array();
         foreach ($key_values as $key) {
             $cache_keys1[] = 'clog#' . $object_type . '#' . $key;
         }
         foreach ($key_values as $key) {
             $cache_keys2[] = 'clogmd5#' . $object_type . '#' . $key;
         }
         $cached_values1 = Cache::get_many($cache_keys1);
         $cached_values2 = Cache::get_many($cache_keys2);
         if (!$fulldump_mode) {
             Cache::delete_many($cache_keys1);
             Cache::delete_many($cache_keys2);
         }
         unset($cache_keys1);
         unset($cache_keys2);
     }
     # Get the current values for objects. Compare them with their previous versions
     # and generate changelog entries.
     require_once $GLOBALS['rootpath'] . 'okapi/service_runner.php';
     $current_values = OkapiServiceRunner::call($feeder_method, new OkapiInternalRequest(new OkapiInternalConsumer(), null, array($feeder_keys_param => implode("|", $key_values), 'fields' => $fields, 'attribution_append' => 'static')));
     $entries = array();
     foreach ($current_values as $key => $object) {
         if ($object !== null) {
             # Currently, the object exists.
             if ($use_cache) {
                 # First, compare the cached hash. The hash has much longer lifetime
                 # than the actual cached object.
                 $cached_md5 = $cached_values2['clogmd5#' . $object_type . '#' . $key];
                 $current_md5 = md5(serialize($object));
                 if ($cached_md5 == $current_md5) {
                     # The object was not changed since it was last replaced.
                     continue;
                 }
                 $diff = self::get_diff($cached_values1['clog#' . $object_type . '#' . $key], $object);
                 if (count($diff) == 0) {
                     # Md5 differs, but diff does not. Weird, but it can happen
                     # (e.g. just after the md5 extension was introduced, or if
                     # md5 somehow expired before the actual object did).
                     continue;
                 }
             }
             $entries[] = array('object_type' => $object_type, 'object_key' => array($key_name => $key), 'change_type' => 'replace', 'data' => $use_cache ? $diff : $object);
             if ($use_cache) {
                 # Save the last-published state of the object, for future comparison.
                 $cached_values2['clogmd5#' . $object_type . '#' . $key] = $current_md5;
                 $cached_values1['clog#' . $object_type . '#' . $key] = $object;
             }
         } else {
             # Currently, the object does not exist.
             if ($use_cache && $cached_values1['clog#' . $object_type . '#' . $key] === false) {
                 # No need to delete, we have already published its deletion.
                 continue;
             }
             $entries[] = array('object_type' => $object_type, 'object_key' => array($key_name => $key), 'change_type' => 'delete');
             if ($use_cache) {
                 # Cache the fact, that the object was deleted.
                 $cached_values2['clogmd5#' . $object_type . '#' . $key] = false;
                 $cached_values1['clog#' . $object_type . '#' . $key] = false;
             }
         }
     }
     if ($fulldump_mode) {
         return $entries;
     } else {
         # Save the entries to the clog table.
         if (count($entries) > 0) {
             $data_values = array();
             foreach ($entries as $entry) {
                 $data_values[] = gzdeflate(serialize($entry));
             }
             Db::execute("\n                    insert into okapi_clog (data)\n                    values ('" . implode("'),('", array_map('mysql_real_escape_string', $data_values)) . "');\n                ");
         }
         # Update the values kept in OKAPI cache.
         if ($use_cache) {
             Cache::set_many($cached_values1, $cache_timeout);
             Cache::set_many($cached_values2, null);
             # make it persistent
         }
     }
 }
Example #2
0
 /** Same as `cache_get`, but it works on multiple keys at once. */
 public static function get_many($keys)
 {
     $prefixed_keys = array();
     foreach ($keys as $key) {
         $prefixed_keys[] = "facade#" . $key;
     }
     $prefixed_result = Cache::get_many($prefixed_keys);
     $result = array();
     foreach ($prefixed_result as $prefixed_key => &$value_ref) {
         $result[substr($prefixed_key, 7)] =& $value_ref;
     }
     return $result;
 }