Example #1
0
 private static function removeStaleDiskCacheItems()
 {
     if (__CA_CACHE_BACKEND__ != 'file') {
         return false;
     }
     // the other backends *should* honor the TTL we pass
     $vs_cache_base_dir = defined('__CA_CACHE_FILEPATH__') ? __CA_CACHE_FILEPATH__ : __CA_APP_DIR__ . DIRECTORY_SEPARATOR . 'tmp';
     $vs_cache_dir = $vs_cache_base_dir . DIRECTORY_SEPARATOR . __CA_APP_NAME__ . 'Cache';
     $va_list = caGetDirectoryContentsAsList($vs_cache_dir);
     foreach ($va_list as $vs_file) {
         $r = @fopen($vs_file, "r");
         if (!is_resource($r)) {
             continue;
         }
         // skip if for some reason the file couldn't be opened
         if (false !== ($vs_line = fgets($r))) {
             $vn_lifetime = (int) $vs_line;
             if ($vn_lifetime !== 0 && $vn_lifetime < time()) {
                 fclose($r);
                 @unlink($vs_file);
             }
         }
     }
     return true;
 }
 private static function removeStaleDiskCacheItems()
 {
     if (__CA_CACHE_BACKEND__ != 'file') {
         return false;
     }
     // the other backends *should* honor the TTL we pass
     $vs_cache_base_dir = defined('__CA_CACHE_FILEPATH__') ? __CA_CACHE_FILEPATH__ : __CA_APP_DIR__ . DIRECTORY_SEPARATOR . 'tmp';
     $vs_cache_dir = $vs_cache_base_dir . DIRECTORY_SEPARATOR . __CA_APP_NAME__ . 'Cache';
     $va_list = caGetDirectoryContentsAsList($vs_cache_dir);
     foreach ($va_list as $vs_file) {
         $r = @fopen($vs_file, "r");
         if (!is_resource($r)) {
             continue;
         }
         // skip if for some reason the file couldn't be opened
         if (false !== ($vs_line = fgets($r))) {
             $vn_lifetime = (int) $vs_line;
             if ($vn_lifetime !== 0 && $vn_lifetime < time()) {
                 fclose($r);
                 @unlink($vs_file);
             }
         }
     }
     $va_dir_list = caGetSubDirectoryList($vs_cache_dir);
     // note we're explicitly reversing the array here so that
     // the order is /foo/bar/foobar, then /foo/bar and then /foo
     // that way we don't need recursion because we just work our way up the directory tree
     foreach (array_reverse($va_dir_list) as $vs_dir => $vn_c) {
         if (caDirectoryIsEmpty($vs_dir)) {
             @rmdir($vs_dir);
         }
     }
     return true;
 }
/**
 * Returns a sorted list of XML profiles. Keys are display names and values are profile codes (filename without .xml extension).
 *
 * @param string $ps_install_dir_prefix optional prefix for install dir
 * @return array List of available profiles
 */
function caGetAvailableXMLProfiles($ps_install_dir_prefix = '.')
{
    $va_files = caGetDirectoryContentsAsList($ps_install_dir_prefix . '/profiles/xml', false);
    $va_profiles = array();
    foreach ($va_files as $vs_filepath) {
        if (preg_match("!\\.xml\$!", $vs_filepath)) {
            $va_tmp = explode('/', $vs_filepath);
            $va_tmp2 = explode('.', array_pop($va_tmp));
            $vs_file = array_shift($va_tmp2);
            $va_profile_info = Installer::getProfileInfo($ps_install_dir_prefix . '/profiles/xml', $vs_file);
            if (!$va_profile_info['useForConfiguration']) {
                continue;
            }
            $va_profiles[$va_profile_info['display']] = $vs_file;
        }
    }
    ksort($va_profiles);
    return $va_profiles;
}
 public function __construct(&$po_request, &$po_response, $pa_view_paths = null)
 {
     global $allowed_universes;
     parent::__construct($po_request, $po_response, $pa_view_paths);
     if (!$this->request->user->canDoAction('can_use_statistics_viewer_plugin')) {
         $this->response->setRedirect($this->request->config->get('error_display_url') . '/n/3000?r=' . urlencode($this->request->getFullUrlPath()));
         return;
     }
     $this->opo_config = Configuration::load(__CA_APP_DIR__ . '/plugins/statisticsViewer/conf/statisticsViewer.conf');
     // Get directory list
     $va_file_list = caGetDirectoryContentsAsList(__CA_APP_DIR__ . "/plugins/statisticsViewer/" . $this->opo_config->get('XmlStatisticsRootDirectory'), false, false);
     $va_dir_list_with_file_counts = caGetSubDirectoryList($this->opo_config->get('importRootDirectory'), true, false);
     $this->opa_statistics_xml_files = array();
     $this->opa_statistics = array();
     if (is_array($allowed_universes = $this->opo_config->getAssoc('AvailableUniversesForStats'))) {
         // if the conf variable AvailableUniversesFor stats is defined
         //echo "here.";
     }
     $this->get_statistics_listing($va_file_list, $allowed_universes);
 }
Example #5
0
 /**
  * Perform media processing for the given field if something has been uploaded
  *
  * @access private
  * @param string $ps_field field name
  * @param array options
  * 
  * Supported options:
  * 		delete_old_media = set to zero to prevent that old media files are deleted; defaults to 1
  *		these_versions_only = if set to an array of valid version names, then only the specified versions are updated with the currently updated file; ignored if no media already exists
  *		dont_allow_duplicate_media = if set to true, and the model as a field named "md5" then media will be rejected if a row already exists with the same MD5 signature
  */
 public function _processMedia($ps_field, $pa_options = null)
 {
     global $AUTH_CURRENT_USER_ID;
     if (!is_array($pa_options)) {
         $pa_options = array();
     }
     if (!isset($pa_options['delete_old_media'])) {
         $pa_options['delete_old_media'] = true;
     }
     if (!isset($pa_options['these_versions_only'])) {
         $pa_options['these_versions_only'] = null;
     }
     $vs_sql = "";
     $vn_max_execution_time = ini_get('max_execution_time');
     set_time_limit(7200);
     $o_tq = new TaskQueue();
     $o_media_proc_settings = new MediaProcessingSettings($this, $ps_field);
     # only set file if something was uploaded
     # (ie. don't nuke an existing file because none
     #      was uploaded)
     $va_field_info = $this->getFieldInfo($ps_field);
     if (isset($this->_FILES_CLEAR[$ps_field]) && $this->_FILES_CLEAR[$ps_field]) {
         //
         // Clear files
         //
         $va_versions = $this->getMediaVersions($ps_field);
         #--- delete files
         foreach ($va_versions as $v) {
             $this->_removeMedia($ps_field, $v);
         }
         $this->_removeMedia($ps_field, '_undo_');
         $this->_FILES[$ps_field] = null;
         $this->_FIELD_VALUES[$ps_field] = null;
         $vs_sql = "{$ps_field} = " . $this->quote(caSerializeForDatabase($this->_FILES[$ps_field], true)) . ",";
     } else {
         // Don't try to process files when no file is actually set
         if (isset($this->_SET_FILES[$ps_field]['tmp_name'])) {
             $o_tq = new TaskQueue();
             $o_media_proc_settings = new MediaProcessingSettings($this, $ps_field);
             //
             // Process incoming files
             //
             $m = new Media();
             $va_media_objects = array();
             // is it a URL?
             $vs_url_fetched_from = null;
             $vn_url_fetched_on = null;
             $vb_allow_fetching_of_urls = (bool) $this->_CONFIG->get('allow_fetching_of_media_from_remote_urls');
             $vb_is_fetched_file = false;
             if ($vb_allow_fetching_of_urls && (bool) ini_get('allow_url_fopen') && isURL($vs_url = html_entity_decode($this->_SET_FILES[$ps_field]['tmp_name']))) {
                 $vs_tmp_file = tempnam(__CA_APP_DIR__ . '/tmp', 'caUrlCopy');
                 $r_incoming_fp = fopen($vs_url, 'r');
                 if (!$r_incoming_fp) {
                     $this->postError(1600, _t('Cannot open remote URL [%1] to fetch media', $vs_url), "BaseModel->_processMedia()", $this->tableName() . '.' . $ps_field);
                     set_time_limit($vn_max_execution_time);
                     return false;
                 }
                 $r_outgoing_fp = fopen($vs_tmp_file, 'w');
                 if (!$r_outgoing_fp) {
                     $this->postError(1600, _t('Cannot open file for media fetched from URL [%1]', $vs_url), "BaseModel->_processMedia()", $this->tableName() . '.' . $ps_field);
                     set_time_limit($vn_max_execution_time);
                     return false;
                 }
                 while (($vs_content = fgets($r_incoming_fp, 4096)) !== false) {
                     fwrite($r_outgoing_fp, $vs_content);
                 }
                 fclose($r_incoming_fp);
                 fclose($r_outgoing_fp);
                 $vs_url_fetched_from = $vs_url;
                 $vn_url_fetched_on = time();
                 $this->_SET_FILES[$ps_field]['tmp_name'] = $vs_tmp_file;
                 $vb_is_fetched_file = true;
             }
             // is it server-side stored user media?
             if (preg_match("!^userMedia[\\d]+/!", $this->_SET_FILES[$ps_field]['tmp_name'])) {
                 // use configured directory to dump media with fallback to standard tmp directory
                 if (!is_writeable($vs_tmp_directory = $this->getAppConfig()->get('ajax_media_upload_tmp_directory'))) {
                     $vs_tmp_directory = caGetTempDirPath();
                 }
                 $this->_SET_FILES[$ps_field]['tmp_name'] = "{$vs_tmp_directory}/" . $this->_SET_FILES[$ps_field]['tmp_name'];
                 // read metadata
                 if (file_exists("{$vs_tmp_directory}/" . $this->_SET_FILES[$ps_field]['tmp_name'] . "_metadata")) {
                     if (is_array($va_tmp_metadata = json_decode(file_get_contents("{$vs_tmp_directory}/" . $this->_SET_FILES[$ps_field]['tmp_name'] . "_metadata")))) {
                         $this->_SET_FILES[$ps_field]['original_filename'] = $va_tmp_metadata['original_filename'];
                     }
                 }
             }
             if (isset($this->_SET_FILES[$ps_field]['tmp_name']) && file_exists($this->_SET_FILES[$ps_field]['tmp_name'])) {
                 if (!isset($pa_options['dont_allow_duplicate_media'])) {
                     $pa_options['dont_allow_duplicate_media'] = (bool) $this->getAppConfig()->get('dont_allow_duplicate_media');
                 }
                 if (isset($pa_options['dont_allow_duplicate_media']) && $pa_options['dont_allow_duplicate_media']) {
                     if ($this->hasField('md5')) {
                         $qr_dupe_chk = $this->getDb()->query("\n\t\t\t\t\t\t\t\tSELECT " . $this->primaryKey() . " FROM " . $this->tableName() . " WHERE md5 = ? " . ($this->hasField('deleted') ? ' AND deleted = 0' : '') . "\n\t\t\t\t\t\t\t", (string) md5_file($this->_SET_FILES[$ps_field]['tmp_name']));
                         if ($qr_dupe_chk->nextRow()) {
                             $this->postError(1600, _t("Media already exists in database"), "BaseModel->_processMedia()", $this->tableName() . '.' . $ps_field);
                             return false;
                         }
                     }
                 }
                 // allow adding zip and (gzipped) tape archives
                 $vb_is_archive = false;
                 $vs_original_filename = $this->_SET_FILES[$ps_field]['original_filename'];
                 $vs_original_tmpname = $this->_SET_FILES[$ps_field]['tmp_name'];
                 $va_matches = array();
                 if (preg_match("/(\\.zip|\\.tar\\.gz|\\.tgz)\$/", $vs_original_filename, $va_matches)) {
                     $vs_archive_extension = $va_matches[1];
                     // add file extension to temporary file if necessary; otherwise phar barfs when handling the archive
                     $va_tmp = array();
                     preg_match("/[.]*\\.([a-zA-Z0-9]+)\$/", $vs_original_tmpname, $va_tmp);
                     if (!isset($va_tmp[1])) {
                         @rename($this->_SET_FILES[$ps_field]['tmp_name'], $this->_SET_FILES[$ps_field]['tmp_name'] . $vs_archive_extension);
                         $this->_SET_FILES[$ps_field]['tmp_name'] = $this->_SET_FILES[$ps_field]['tmp_name'] . $vs_archive_extension;
                     }
                     if (caIsArchive($this->_SET_FILES[$ps_field]['tmp_name'])) {
                         $va_archive_files = caGetDirectoryContentsAsList('phar://' . $this->_SET_FILES[$ps_field]['tmp_name']);
                         if (sizeof($va_archive_files) > 0) {
                             // get first file we encounter in the archive and use it to generate them previews
                             $vb_is_archive = true;
                             $vs_archive = $this->_SET_FILES[$ps_field]['tmp_name'];
                             $va_tmp = array();
                             // copy primary file from the archive to temporary file (with extension so that *Magick can identify properly)
                             // this is basically a fallback. if the code below fails, we still have a 'fake' original
                             preg_match("/[.]*\\.([a-zA-Z0-9]+)\$/", $va_archive_files[0], $va_tmp);
                             $vs_primary_file_tmp = tempnam(caGetTempDirPath(), "caArchivePrimary");
                             @unlink($vs_primary_file_tmp);
                             $vs_primary_file_tmp = $vs_primary_file_tmp . "." . $va_tmp[1];
                             if (!@copy($va_archive_files[0], $vs_primary_file_tmp)) {
                                 $this->postError(1600, _t("Couldn't extract first file from archive. There is probably a invalid character in a directory or file name inside the archive"), "BaseModel->_processMedia()", $this->tableName() . '.' . $ps_field);
                                 set_time_limit($vn_max_execution_time);
                                 if ($vb_is_fetched_file) {
                                     @unlink($vs_tmp_file);
                                 }
                                 if ($vb_is_archive) {
                                     @unlink($vs_archive);
                                     @unlink($vs_primary_file_tmp);
                                 }
                                 return false;
                             }
                             $this->_SET_FILES[$ps_field]['tmp_name'] = $vs_primary_file_tmp;
                             // prepare to join archive contents to form a better downloadable "original" than the zip/tgz archive (e.g. a multi-page tiff)
                             // to do that, we have to 'extract' the archive so that command-line utilities like *Magick can operate
                             @caRemoveDirectory(caGetTempDirPath() . '/caArchiveExtract');
                             // remove left-overs, just to be sure we don't include other files in the tiff
                             $va_archive_tmp_files = array();
                             @mkdir(caGetTempDirPath() . '/caArchiveExtract');
                             foreach ($va_archive_files as $vs_archive_file) {
                                 $vs_basename = basename($vs_archive_file);
                                 $vs_tmp_file_name = caGetTempDirPath() . '/caArchiveExtract/' . str_replace(" ", "_", $vs_basename);
                                 $va_archive_tmp_files[] = $vs_tmp_file_name;
                                 @copy($vs_archive_file, $vs_tmp_file_name);
                             }
                         }
                     }
                     if (!$vb_is_archive) {
                         // something went wrong (i.e. no valid or empty archive) -> restore previous state
                         @rename($this->_SET_FILES[$ps_field]['tmp_name'] . $vs_archive_extension, $vs_original_tmpname);
                         $this->_SET_FILES[$ps_field]['tmp_name'] = $vs_original_tmpname;
                     }
                 }
                 // ImageMagick partly relies on file extensions to properly identify images (RAW images in particular)
                 // therefore we rename the temporary file here (using the extension of the original filename, if any)
                 $va_matches = array();
                 $vb_renamed_tmpfile = false;
                 preg_match("/[.]*\\.([a-zA-Z0-9]+)\$/", $this->_SET_FILES[$ps_field]['tmp_name'], $va_matches);
                 if (!isset($va_matches[1])) {
                     // file has no extension, i.e. is probably PHP upload tmp file
                     $va_matches = array();
                     preg_match("/[.]*\\.([a-zA-Z0-9]+)\$/", $this->_SET_FILES[$ps_field]['original_filename'], $va_matches);
                     if (strlen($va_matches[1]) > 0) {
                         $va_parts = explode("/", $this->_SET_FILES[$ps_field]['tmp_name']);
                         $vs_new_filename = sys_get_temp_dir() . "/" . $va_parts[sizeof($va_parts) - 1] . "." . $va_matches[1];
                         if (!move_uploaded_file($this->_SET_FILES[$ps_field]['tmp_name'], $vs_new_filename)) {
                             rename($this->_SET_FILES[$ps_field]['tmp_name'], $vs_new_filename);
                         }
                         $this->_SET_FILES[$ps_field]['tmp_name'] = $vs_new_filename;
                         $vb_renamed_tmpfile = true;
                     }
                 }
                 $input_mimetype = $m->divineFileFormat($this->_SET_FILES[$ps_field]['tmp_name']);
                 if (!($input_type = $o_media_proc_settings->canAccept($input_mimetype))) {
                     # error - filetype not accepted by this field
                     $this->postError(1600, $input_mimetype ? _t("File type %1 not accepted by %2", $input_mimetype, $ps_field) : _t("Unknown file type not accepted by %1", $ps_field), "BaseModel->_processMedia()", $this->tableName() . '.' . $ps_field);
                     set_time_limit($vn_max_execution_time);
                     if ($vb_is_fetched_file) {
                         @unlink($vs_tmp_file);
                     }
                     if ($vb_is_archive) {
                         @unlink($vs_archive);
                         @unlink($vs_primary_file_tmp);
                     }
                     return false;
                 }
                 # ok process file...
                 if (!$m->read($this->_SET_FILES[$ps_field]['tmp_name'])) {
                     $this->errors = array_merge($this->errors, $m->errors());
                     // copy into model plugin errors
                     set_time_limit($vn_max_execution_time);
                     if ($vb_is_fetched_file) {
                         @unlink($vs_tmp_file);
                     }
                     if ($vb_is_archive) {
                         @unlink($vs_archive);
                         @unlink($vs_primary_file_tmp);
                     }
                     return false;
                 }
                 // if necessary, join archive contents to form a better downloadable "original" than the zip/tgz archive (e.g. a multi-page tiff)
                 // by this point, a backend plugin was picked using the first file of the archive. this backend is also used to prepare the new original.
                 if ($vb_is_archive && sizeof($va_archive_tmp_files) > 0) {
                     if ($vs_archive_original = $m->joinArchiveContents($va_archive_tmp_files)) {
                         // mangle filename, so that the uploaded archive.zip becomes archive.tif or archive.gif or whatever extension the Media plugin prefers
                         $va_new_original_pathinfo = pathinfo($vs_archive_original);
                         $va_archive_pathinfo = pathinfo($this->_SET_FILES[$ps_field]['original_filename']);
                         $this->_SET_FILES[$ps_field]['original_filename'] = $va_archive_pathinfo['filename'] . "." . $va_new_original_pathinfo['extension'];
                         // this is now our original, disregard the uploaded archive
                         $this->_SET_FILES[$ps_field]['tmp_name'] = $vs_archive_original;
                         // re-run mimetype detection and read on the new original
                         $m->reset();
                         $input_mimetype = $m->divineFileFormat($vs_archive_original);
                         $input_type = $o_media_proc_settings->canAccept($input_mimetype);
                         $m->read($vs_archive_original);
                     }
                     @caRemoveDirectory(caGetTempDirPath() . '/caArchiveExtract');
                 }
                 $va_media_objects['_original'] = $m;
                 // preserve center setting from any existing media
                 $va_center = null;
                 if (is_array($va_tmp = $this->getMediaInfo($ps_field))) {
                     $va_center = caGetOption('_CENTER', $va_tmp, array());
                 }
                 $media_desc = array("ORIGINAL_FILENAME" => $this->_SET_FILES[$ps_field]['original_filename'], "_CENTER" => $va_center, "_SCALE" => caGetOption('_SCALE', $va_tmp, array()), "_SCALE_UNITS" => caGetOption('_SCALE_UNITS', $va_tmp, array()), "INPUT" => array("MIMETYPE" => $m->get("mimetype"), "WIDTH" => $m->get("width"), "HEIGHT" => $m->get("height"), "MD5" => md5_file($this->_SET_FILES[$ps_field]['tmp_name']), "FILESIZE" => filesize($this->_SET_FILES[$ps_field]['tmp_name']), "FETCHED_FROM" => $vs_url_fetched_from, "FETCHED_ON" => $vn_url_fetched_on));
                 if (isset($this->_SET_FILES[$ps_field]['options']['TRANSFORMATION_HISTORY']) && is_array($this->_SET_FILES[$ps_field]['options']['TRANSFORMATION_HISTORY'])) {
                     $media_desc['TRANSFORMATION_HISTORY'] = $this->_SET_FILES[$ps_field]['options']['TRANSFORMATION_HISTORY'];
                 }
                 #
                 # Extract metadata from file
                 #
                 $media_metadata = $m->getExtractedMetadata();
                 # get versions to create
                 $va_versions = $this->getMediaVersions($ps_field, $input_mimetype);
                 $error = 0;
                 # don't process files that are not going to be processed or converted
                 # we don't want to waste time opening file we're not going to do anything with
                 # also, we don't want to recompress JPEGs...
                 $media_type = $o_media_proc_settings->canAccept($input_mimetype);
                 $version_info = $o_media_proc_settings->getMediaTypeVersions($media_type);
                 $va_default_queue_settings = $o_media_proc_settings->getMediaTypeQueueSettings($media_type);
                 if (!($va_media_write_options = $this->_FILES[$ps_field]['options'])) {
                     $va_media_write_options = $this->_SET_FILES[$ps_field]['options'];
                 }
                 # Is an "undo" version set in options?
                 if (isset($this->_SET_FILES[$ps_field]['options']['undo']) && file_exists($this->_SET_FILES[$ps_field]['options']['undo'])) {
                     if ($volume = $version_info['original']['VOLUME']) {
                         $vi = $this->_MEDIA_VOLUMES->getVolumeInformation($volume);
                         if ($vi["absolutePath"] && strlen($dirhash = $this->_getDirectoryHash($vi["absolutePath"], $this->getPrimaryKey()))) {
                             $magic = rand(0, 99999);
                             $vs_filename = $this->_genMediaName($ps_field) . "_undo_";
                             $filepath = $vi["absolutePath"] . "/" . $dirhash . "/" . $magic . "_" . $vs_filename;
                             if (copy($this->_SET_FILES[$ps_field]['options']['undo'], $filepath)) {
                                 $media_desc['_undo_'] = array("VOLUME" => $volume, "FILENAME" => $vs_filename, "HASH" => $dirhash, "MAGIC" => $magic, "MD5" => md5_file($filepath));
                             }
                         }
                     }
                 }
                 $va_process_these_versions_only = array();
                 if (isset($pa_options['these_versions_only']) && is_array($pa_options['these_versions_only']) && sizeof($pa_options['these_versions_only'])) {
                     $va_tmp = $this->_FIELD_VALUES[$ps_field];
                     foreach ($pa_options['these_versions_only'] as $vs_this_version_only) {
                         if (in_array($vs_this_version_only, $va_versions)) {
                             if (is_array($this->_FIELD_VALUES[$ps_field])) {
                                 $va_process_these_versions_only[] = $vs_this_version_only;
                             }
                         }
                     }
                     // Copy metadata for version we're not processing
                     if (sizeof($va_process_these_versions_only)) {
                         foreach (array_keys($va_tmp) as $v) {
                             if (!in_array($v, $va_process_these_versions_only)) {
                                 $media_desc[$v] = $va_tmp[$v];
                             }
                         }
                     }
                 }
                 $va_files_to_delete = array();
                 $va_queued_versions = array();
                 $queue_enabled = !sizeof($va_process_these_versions_only) && $this->getAppConfig()->get('queue_enabled') ? true : false;
                 $vs_path_to_queue_media = null;
                 foreach ($va_versions as $v) {
                     $vs_use_icon = null;
                     if (sizeof($va_process_these_versions_only) && !in_array($v, $va_process_these_versions_only)) {
                         // only processing certain versions... and this one isn't it so skip
                         continue;
                     }
                     $queue = $va_default_queue_settings['QUEUE'];
                     $queue_threshold = isset($version_info[$v]['QUEUE_WHEN_FILE_LARGER_THAN']) ? intval($version_info[$v]['QUEUE_WHEN_FILE_LARGER_THAN']) : (int) $va_default_queue_settings['QUEUE_WHEN_FILE_LARGER_THAN'];
                     $rule = isset($version_info[$v]['RULE']) ? $version_info[$v]['RULE'] : '';
                     $volume = isset($version_info[$v]['VOLUME']) ? $version_info[$v]['VOLUME'] : '';
                     $basis = isset($version_info[$v]['BASIS']) ? $version_info[$v]['BASIS'] : '';
                     if (isset($media_desc[$basis]) && isset($media_desc[$basis]['FILENAME'])) {
                         if (!isset($va_media_objects[$basis])) {
                             $o_media = new Media();
                             $basis_vi = $this->_MEDIA_VOLUMES->getVolumeInformation($media_desc[$basis]['VOLUME']);
                             if ($o_media->read($p = $basis_vi['absolutePath'] . "/" . $media_desc[$basis]['HASH'] . "/" . $media_desc[$basis]['MAGIC'] . "_" . $media_desc[$basis]['FILENAME'])) {
                                 $va_media_objects[$basis] = $o_media;
                             } else {
                                 $m = $va_media_objects['_original'];
                             }
                         } else {
                             $m = $va_media_objects[$basis];
                         }
                     } else {
                         $m = $va_media_objects['_original'];
                     }
                     $m->reset();
                     # get volume
                     $vi = $this->_MEDIA_VOLUMES->getVolumeInformation($volume);
                     if (!is_array($vi)) {
                         print "Invalid volume '{$volume}'<br>";
                         exit;
                     }
                     // Send to queue if it's too big to process here
                     if ($queue_enabled && $queue && $queue_threshold > 0 && $queue_threshold < (int) $media_desc["INPUT"]["FILESIZE"] && $va_default_queue_settings['QUEUE_USING_VERSION'] != $v) {
                         $va_queued_versions[$v] = array('VOLUME' => $volume);
                         $media_desc[$v]["QUEUED"] = $queue;
                         if ($version_info[$v]["QUEUED_MESSAGE"]) {
                             $media_desc[$v]["QUEUED_MESSAGE"] = $version_info[$v]["QUEUED_MESSAGE"];
                         } else {
                             $media_desc[$v]["QUEUED_MESSAGE"] = $va_default_queue_settings['QUEUED_MESSAGE'] ? $va_default_queue_settings['QUEUED_MESSAGE'] : _t("Media is being processed and will be available shortly.");
                         }
                         if ($pa_options['delete_old_media']) {
                             $va_files_to_delete[] = array('field' => $ps_field, 'version' => $v);
                         }
                         continue;
                     }
                     # get transformation rules
                     $rules = $o_media_proc_settings->getMediaTransformationRule($rule);
                     if (sizeof($rules) == 0) {
                         $output_mimetype = $input_mimetype;
                         $m->set("version", $v);
                         #
                         # don't process this media, just copy the file
                         #
                         $ext = $m->mimetype2extension($output_mimetype);
                         if (!$ext) {
                             $this->postError(1600, _t("File could not be copied for %1; can't convert mimetype '%2' to extension", $ps_field, $output_mimetype), "BaseModel->_processMedia()", $this->tableName() . '.' . $ps_field);
                             $m->cleanup();
                             set_time_limit($vn_max_execution_time);
                             if ($vb_is_fetched_file) {
                                 @unlink($vs_tmp_file);
                             }
                             if ($vb_is_archive) {
                                 @unlink($vs_archive);
                                 @unlink($vs_primary_file_tmp);
                                 @unlink($vs_archive_original);
                             }
                             return false;
                         }
                         if (($dirhash = $this->_getDirectoryHash($vi["absolutePath"], $this->getPrimaryKey())) === false) {
                             $this->postError(1600, _t("Could not create subdirectory for uploaded file in %1. Please ask your administrator to check the permissions of your media directory.", $vi["absolutePath"]), "BaseModel->_processMedia()", $this->tableName() . '.' . $ps_field);
                             set_time_limit($vn_max_execution_time);
                             if ($vb_is_fetched_file) {
                                 @unlink($vs_tmp_file);
                             }
                             if ($vb_is_archive) {
                                 @unlink($vs_archive);
                                 @unlink($vs_primary_file_tmp);
                                 @unlink($vs_archive_original);
                             }
                             return false;
                         }
                         if ((bool) $version_info[$v]["USE_EXTERNAL_URL_WHEN_AVAILABLE"]) {
                             $filepath = $this->_SET_FILES[$ps_field]['tmp_name'];
                             if ($pa_options['delete_old_media']) {
                                 $va_files_to_delete[] = array('field' => $ps_field, 'version' => $v);
                             }
                             $media_desc[$v] = array("VOLUME" => $volume, "MIMETYPE" => $output_mimetype, "WIDTH" => $m->get("width"), "HEIGHT" => $m->get("height"), "PROPERTIES" => $m->getProperties(), "EXTERNAL_URL" => $media_desc['INPUT']['FETCHED_FROM'], "FILENAME" => null, "HASH" => null, "MAGIC" => null, "EXTENSION" => $ext, "MD5" => md5_file($filepath));
                         } else {
                             $magic = rand(0, 99999);
                             $filepath = $vi["absolutePath"] . "/" . $dirhash . "/" . $magic . "_" . $this->_genMediaName($ps_field) . "_" . $v . "." . $ext;
                             if (!copy($this->_SET_FILES[$ps_field]['tmp_name'], $filepath)) {
                                 $this->postError(1600, _t("File could not be copied. Ask your administrator to check permissions and file space for %1", $vi["absolutePath"]), "BaseModel->_processMedia()", $this->tableName() . '.' . $ps_field);
                                 $m->cleanup();
                                 set_time_limit($vn_max_execution_time);
                                 if ($vb_is_fetched_file) {
                                     @unlink($vs_tmp_file);
                                 }
                                 if ($vb_is_archive) {
                                     @unlink($vs_archive);
                                     @unlink($vs_primary_file_tmp);
                                     @unlink($vs_archive_original);
                                 }
                                 return false;
                             }
                             if ($v === $va_default_queue_settings['QUEUE_USING_VERSION']) {
                                 $vs_path_to_queue_media = $filepath;
                             }
                             if ($pa_options['delete_old_media']) {
                                 $va_files_to_delete[] = array('field' => $ps_field, 'version' => $v, 'dont_delete_path' => $vi["absolutePath"] . "/" . $dirhash . "/" . $magic . "_" . $this->_genMediaName($ps_field) . "_" . $v, 'dont_delete_extension' => $ext);
                             }
                             if (is_array($vi["mirrors"]) && sizeof($vi["mirrors"]) > 0) {
                                 $vs_entity_key = join("/", array($this->tableName(), $ps_field, $this->getPrimaryKey(), $v));
                                 $vs_row_key = join("/", array($this->tableName(), $this->getPrimaryKey()));
                                 foreach ($vi["mirrors"] as $vs_mirror_code => $va_mirror_info) {
                                     $vs_mirror_method = $va_mirror_info["method"];
                                     $vs_queue = $vs_mirror_method . "mirror";
                                     if (!$o_tq->cancelPendingTasksForEntity($vs_entity_key)) {
                                         //$this->postError(560, _t("Could not cancel pending tasks: %1", $this->error),"BaseModel->_processMedia()");
                                         //$m->cleanup();
                                         //return false;
                                     }
                                     if ($o_tq->addTask($vs_queue, array("MIRROR" => $vs_mirror_code, "VOLUME" => $volume, "FIELD" => $ps_field, "TABLE" => $this->tableName(), "VERSION" => $v, "FILES" => array(array("FILE_PATH" => $filepath, "ABS_PATH" => $vi["absolutePath"], "HASH" => $dirhash, "FILENAME" => $magic . "_" . $this->_genMediaName($ps_field) . "_" . $v . "." . $ext)), "MIRROR_INFO" => $va_mirror_info, "PK" => $this->primaryKey(), "PK_VAL" => $this->getPrimaryKey()), array("priority" => 100, "entity_key" => $vs_entity_key, "row_key" => $vs_row_key, 'user_id' => $AUTH_CURRENT_USER_ID))) {
                                         continue;
                                     } else {
                                         $this->postError(100, _t("Couldn't queue mirror using '%1' for version '%2' (handler '%3')", $vs_mirror_method, $v, $queue), "BaseModel->_processMedia()");
                                     }
                                 }
                             }
                             $media_desc[$v] = array("VOLUME" => $volume, "MIMETYPE" => $output_mimetype, "WIDTH" => $m->get("width"), "HEIGHT" => $m->get("height"), "PROPERTIES" => $m->getProperties(), "FILENAME" => $this->_genMediaName($ps_field) . "_" . $v . "." . $ext, "HASH" => $dirhash, "MAGIC" => $magic, "EXTENSION" => $ext, "MD5" => md5_file($filepath));
                         }
                     } else {
                         $m->set("version", $v);
                         while (list($operation, $parameters) = each($rules)) {
                             if ($operation === 'SET') {
                                 foreach ($parameters as $pp => $pv) {
                                     if ($pp == 'format') {
                                         $output_mimetype = $pv;
                                     } else {
                                         $m->set($pp, $pv);
                                     }
                                 }
                             } else {
                                 if (is_array($this->_FIELD_VALUES[$ps_field]) && is_array($va_media_center = $this->getMediaCenter($ps_field))) {
                                     $parameters['_centerX'] = caGetOption('x', $va_media_center, 0.5);
                                     $parameters['_centerY'] = caGetOption('y', $va_media_center, 0.5);
                                     if ($parameters['_centerX'] < 0 || $parameters['_centerX'] > 1) {
                                         $parameters['_centerX'] = 0.5;
                                     }
                                     if ($parameters['_centerY'] < 0 || $parameters['_centerY'] > 1) {
                                         $parameters['_centerY'] = 0.5;
                                     }
                                 }
                                 if (!$m->transform($operation, $parameters)) {
                                     $error = 1;
                                     $error_msg = "Couldn't do transformation '{$operation}'";
                                     break 2;
                                 }
                             }
                         }
                         if (!$output_mimetype) {
                             $output_mimetype = $input_mimetype;
                         }
                         if (!($ext = $m->mimetype2extension($output_mimetype))) {
                             $this->postError(1600, _t("File could not be processed for %1; can't convert mimetype '%2' to extension", $ps_field, $output_mimetype), "BaseModel->_processMedia()", $this->tableName() . '.' . $ps_field);
                             $m->cleanup();
                             set_time_limit($vn_max_execution_time);
                             if ($vb_is_fetched_file) {
                                 @unlink($vs_tmp_file);
                             }
                             if ($vb_is_archive) {
                                 @unlink($vs_archive);
                                 @unlink($vs_primary_file_tmp);
                                 @unlink($vs_archive_original);
                             }
                             return false;
                         }
                         if (($dirhash = $this->_getDirectoryHash($vi["absolutePath"], $this->getPrimaryKey())) === false) {
                             $this->postError(1600, _t("Could not create subdirectory for uploaded file in %1. Please ask your administrator to check the permissions of your media directory.", $vi["absolutePath"]), "BaseModel->_processMedia()", $this->tableName() . '.' . $ps_field);
                             set_time_limit($vn_max_execution_time);
                             if ($vb_is_fetched_file) {
                                 @unlink($vs_tmp_file);
                             }
                             if ($vb_is_archive) {
                                 @unlink($vs_archive);
                                 @unlink($vs_primary_file_tmp);
                                 @unlink($vs_archive_original);
                             }
                             return false;
                         }
                         $magic = rand(0, 99999);
                         $filepath = $vi["absolutePath"] . "/" . $dirhash . "/" . $magic . "_" . $this->_genMediaName($ps_field) . "_" . $v;
                         if (!($vs_output_file = $m->write($filepath, $output_mimetype, $va_media_write_options))) {
                             $this->postError(1600, _t("Couldn't write file: %1", join("; ", $m->getErrors())), "BaseModel->_processMedia()", $this->tableName() . '.' . $ps_field);
                             $m->cleanup();
                             set_time_limit($vn_max_execution_time);
                             if ($vb_is_fetched_file) {
                                 @unlink($vs_tmp_file);
                             }
                             if ($vb_is_archive) {
                                 @unlink($vs_archive);
                                 @unlink($vs_primary_file_tmp);
                                 @unlink($vs_archive_original);
                             }
                             return false;
                             break;
                         } else {
                             if ($vs_output_file === __CA_MEDIA_VIDEO_DEFAULT_ICON__ || $vs_output_file === __CA_MEDIA_AUDIO_DEFAULT_ICON__ || $vs_output_file === __CA_MEDIA_DOCUMENT_DEFAULT_ICON__ || $vs_output_file === __CA_MEDIA_3D_DEFAULT_ICON__) {
                                 $vs_use_icon = $vs_output_file;
                             }
                         }
                         if ($v === $va_default_queue_settings['QUEUE_USING_VERSION']) {
                             $vs_path_to_queue_media = $vs_output_file;
                             $vs_use_icon = __CA_MEDIA_QUEUED_ICON__;
                         }
                         if ($pa_options['delete_old_media'] && !$error) {
                             if ($vs_old_media_path = $this->getMediaPath($ps_field, $v)) {
                                 $va_files_to_delete[] = array('field' => $ps_field, 'version' => $v, 'dont_delete_path' => $filepath, 'dont_delete_extension' => $ext);
                             }
                         }
                         if (is_array($vi["mirrors"]) && sizeof($vi["mirrors"]) > 0) {
                             $vs_entity_key = join("/", array($this->tableName(), $ps_field, $this->getPrimaryKey(), $v));
                             $vs_row_key = join("/", array($this->tableName(), $this->getPrimaryKey()));
                             foreach ($vi["mirrors"] as $vs_mirror_code => $va_mirror_info) {
                                 $vs_mirror_method = $va_mirror_info["method"];
                                 $vs_queue = $vs_mirror_method . "mirror";
                                 if (!$o_tq->cancelPendingTasksForEntity($vs_entity_key)) {
                                     //$this->postError(560, _t("Could not cancel pending tasks: %1", $this->error),"BaseModel->_processMedia()");
                                     //$m->cleanup();
                                     //return false;
                                 }
                                 if ($o_tq->addTask($vs_queue, array("MIRROR" => $vs_mirror_code, "VOLUME" => $volume, "FIELD" => $ps_field, "TABLE" => $this->tableName(), "VERSION" => $v, "FILES" => array(array("FILE_PATH" => $filepath . "." . $ext, "ABS_PATH" => $vi["absolutePath"], "HASH" => $dirhash, "FILENAME" => $magic . "_" . $this->_genMediaName($ps_field) . "_" . $v . "." . $ext)), "MIRROR_INFO" => $va_mirror_info, "PK" => $this->primaryKey(), "PK_VAL" => $this->getPrimaryKey()), array("priority" => 100, "entity_key" => $vs_entity_key, "row_key" => $vs_row_key, 'user_id' => $AUTH_CURRENT_USER_ID))) {
                                     continue;
                                 } else {
                                     $this->postError(100, _t("Couldn't queue mirror using '%1' for version '%2' (handler '%3')", $vs_mirror_method, $v, $queue), "BaseModel->_processMedia()");
                                 }
                             }
                         }
                         if ($vs_use_icon) {
                             $media_desc[$v] = array("MIMETYPE" => $output_mimetype, "USE_ICON" => $vs_use_icon, "WIDTH" => $m->get("width"), "HEIGHT" => $m->get("height"));
                         } else {
                             $media_desc[$v] = array("VOLUME" => $volume, "MIMETYPE" => $output_mimetype, "WIDTH" => $m->get("width"), "HEIGHT" => $m->get("height"), "PROPERTIES" => $m->getProperties(), "FILENAME" => $this->_genMediaName($ps_field) . "_" . $v . "." . $ext, "HASH" => $dirhash, "MAGIC" => $magic, "EXTENSION" => $ext, "MD5" => md5_file($vi["absolutePath"] . "/" . $dirhash . "/" . $magic . "_" . $this->_genMediaName($ps_field) . "_" . $v . "." . $ext));
                         }
                         $m->reset();
                     }
                 }
                 if (sizeof($va_queued_versions)) {
                     $vs_entity_key = md5(join("/", array_merge(array($this->tableName(), $ps_field, $this->getPrimaryKey()), array_keys($va_queued_versions))));
                     $vs_row_key = join("/", array($this->tableName(), $this->getPrimaryKey()));
                     if (!$o_tq->cancelPendingTasksForEntity($vs_entity_key, $queue)) {
                         // TODO: log this
                     }
                     if (!($filename = $vs_path_to_queue_media)) {
                         // if we're not using a designated not-queued representation to generate the queued ones
                         // then copy the uploaded file to the tmp dir and use that
                         $filename = $o_tq->copyFileToQueueTmp($va_default_queue_settings['QUEUE'], $this->_SET_FILES[$ps_field]['tmp_name']);
                     }
                     if ($filename) {
                         if ($o_tq->addTask($va_default_queue_settings['QUEUE'], array("TABLE" => $this->tableName(), "FIELD" => $ps_field, "PK" => $this->primaryKey(), "PK_VAL" => $this->getPrimaryKey(), "INPUT_MIMETYPE" => $input_mimetype, "FILENAME" => $filename, "VERSIONS" => $va_queued_versions, "OPTIONS" => $va_media_write_options, "DONT_DELETE_OLD_MEDIA" => $filename == $vs_path_to_queue_media ? true : false), array("priority" => 100, "entity_key" => $vs_entity_key, "row_key" => $vs_row_key, 'user_id' => $AUTH_CURRENT_USER_ID))) {
                             if ($pa_options['delete_old_media']) {
                                 foreach ($va_queued_versions as $vs_version => $va_version_info) {
                                     $va_files_to_delete[] = array('field' => $ps_field, 'version' => $vs_version);
                                 }
                             }
                         } else {
                             $this->postError(100, _t("Couldn't queue processing for version '%1' using handler '%2'", !$v, $queue), "BaseModel->_processMedia()");
                         }
                     } else {
                         $this->errors = $o_tq->errors;
                     }
                 } else {
                     // Generate preview frames for media that support that (Eg. video)
                     // and add them as "multifiles" assuming the current model supports that (ca_object_representations does)
                     if (!sizeof($va_process_these_versions_only) && ((bool) $this->_CONFIG->get('video_preview_generate_frames') || (bool) $this->_CONFIG->get('document_preview_generate_pages')) && method_exists($this, 'addFile')) {
                         if (method_exists($this, 'removeAllFiles')) {
                             $this->removeAllFiles();
                             // get rid of any previously existing frames (they might be hanging ar
                         }
                         $va_preview_frame_list = $m->writePreviews(array('width' => $m->get("width"), 'height' => $m->get("height"), 'minNumberOfFrames' => $this->_CONFIG->get('video_preview_min_number_of_frames'), 'maxNumberOfFrames' => $this->_CONFIG->get('video_preview_max_number_of_frames'), 'numberOfPages' => $this->_CONFIG->get('document_preview_max_number_of_pages'), 'frameInterval' => $this->_CONFIG->get('video_preview_interval_between_frames'), 'pageInterval' => $this->_CONFIG->get('document_preview_interval_between_pages'), 'startAtTime' => $this->_CONFIG->get('video_preview_start_at'), 'endAtTime' => $this->_CONFIG->get('video_preview_end_at'), 'startAtPage' => $this->_CONFIG->get('document_preview_start_page'), 'outputDirectory' => __CA_APP_DIR__ . '/tmp'));
                         if (is_array($va_preview_frame_list)) {
                             foreach ($va_preview_frame_list as $vn_time => $vs_frame) {
                                 $this->addFile($vs_frame, $vn_time, true);
                                 // the resource path for each frame is it's time, in seconds (may be fractional) for video, or page number for documents
                                 @unlink($vs_frame);
                                 // clean up tmp preview frame file
                             }
                         }
                     }
                 }
                 if (!$error) {
                     #
                     # --- Clean up old media from versions that are not supported in the new media
                     #
                     if ($pa_options['delete_old_media']) {
                         foreach ($this->getMediaVersions($ps_field) as $old_version) {
                             if (!is_array($media_desc[$old_version])) {
                                 $this->_removeMedia($ps_field, $old_version);
                             }
                         }
                     }
                     foreach ($va_files_to_delete as $va_file_to_delete) {
                         $this->_removeMedia($va_file_to_delete['field'], $va_file_to_delete['version'], $va_file_to_delete['dont_delete_path'], $va_file_to_delete['dont_delete_extension']);
                     }
                     # Remove old _undo_ file if defined
                     if ($vs_undo_path = $this->getMediaPath($ps_field, '_undo_')) {
                         @unlink($vs_undo_path);
                     }
                     $this->_FILES[$ps_field] = $media_desc;
                     $this->_FIELD_VALUES[$ps_field] = $media_desc;
                     $vs_serialized_data = caSerializeForDatabase($this->_FILES[$ps_field], true);
                     $vs_sql = "{$ps_field} = " . $this->quote($vs_serialized_data) . ",";
                     if (($vs_metadata_field_name = $o_media_proc_settings->getMetadataFieldName()) && $this->hasField($vs_metadata_field_name)) {
                         $this->set($vs_metadata_field_name, $media_metadata);
                         $vs_sql .= " " . $vs_metadata_field_name . " = " . $this->quote(caSerializeForDatabase($media_metadata, true)) . ",";
                     }
                     if (($vs_content_field_name = $o_media_proc_settings->getMetadataContentName()) && $this->hasField($vs_content_field_name)) {
                         $this->_FIELD_VALUES[$vs_content_field_name] = $this->quote($m->getExtractedText());
                         $vs_sql .= " " . $vs_content_field_name . " = " . $this->_FIELD_VALUES[$vs_content_field_name] . ",";
                     }
                     if (is_array($va_locs = $m->getExtractedTextLocations())) {
                         MediaContentLocationIndexer::clear($this->tableNum(), $this->getPrimaryKey());
                         foreach ($va_locs as $vs_content => $va_loc_list) {
                             foreach ($va_loc_list as $va_loc) {
                                 MediaContentLocationIndexer::index($this->tableNum(), $this->getPrimaryKey(), $vs_content, $va_loc['p'], $va_loc['x1'], $va_loc['y1'], $va_loc['x2'], $va_loc['y2']);
                             }
                         }
                         MediaContentLocationIndexer::write();
                     }
                 } else {
                     # error - invalid media
                     $this->postError(1600, _t("File could not be processed for %1: %2", $ps_field, $error_msg), "BaseModel->_processMedia()");
                     #	    return false;
                 }
                 $m->cleanup();
                 if ($vb_renamed_tmpfile) {
                     @unlink($this->_SET_FILES[$ps_field]['tmp_name']);
                 }
             } elseif (is_array($this->_FIELD_VALUES[$ps_field])) {
                 // Just set field values in SQL (assume in-place update of media metadata) because no tmp_name is set
                 // [This generally should not happen]
                 $this->_FILES[$ps_field] = $this->_FIELD_VALUES[$ps_field];
                 $vs_sql = "{$ps_field} = " . $this->quote(caSerializeForDatabase($this->_FILES[$ps_field], true)) . ",";
             }
             $this->_SET_FILES[$ps_field] = null;
         } elseif (is_array($this->_FIELD_VALUES[$ps_field])) {
             // Just set field values in SQL (usually in-place update of media metadata)
             $this->_FILES[$ps_field] = $this->_FIELD_VALUES[$ps_field];
             $vs_sql = "{$ps_field} = " . $this->quote(caSerializeForDatabase($this->_FILES[$ps_field], true)) . ",";
         }
     }
     set_time_limit($vn_max_execution_time);
     if ($vb_is_fetched_file) {
         @unlink($vs_tmp_file);
     }
     if ($vb_is_archive) {
         @unlink($vs_archive);
         @unlink($vs_primary_file_tmp);
         @unlink($vs_archive_original);
     }
     return $vs_sql;
 }
 /**
  * Returns id for the row with the specified name (and type) or idno (regardless of specified type.) If the row does not already
  * exist then it will be created with the specified name, type and locale, as well as with any specified values in the $pa_values array.
  * $pa_values keys should be either valid entity fields or attributes.
  *
  * @param string $ps_table The table to match and/or create rows in
  * @param array $pa_label Array with values for row label
  * @param int $pn_parent_id
  * @param int $pn_type_id The type_id or code of the type to use if the row needs to be created
  * @param int $pn_locale_id The locale_id to use if the row needs to be created (will be used for both the row locale as well as the label locale)
  * @param array $pa_values An optional array of additional values to populate newly created rows with. These values are *only* used for newly created rows; they will not be applied if the row named already exists unless the forceUpdate option is set, in which case attributes (but not intrinsics) will be updated. The array keys should be names of fields or valid attributes. Values should be either a scalar (for single-value attributes) or an array of values for (multi-valued attributes)
  * @param array $pa_options An optional array of options, which include:
  *                outputErrors - if true, errors will be printed to console [default=false]
  *                dontCreate - if true then new entities will not be created [default=false]
  *                matchOn = optional list indicating sequence of checks for an existing record; values of array can be "label" and "idno". Ex. array("idno", "label") will first try to match on idno and then label if the first match fails. For entities only you may also specifiy "displayname", "surname" and "forename" to match on the text of the those label fields exclusively.
  *                matchOnDisplayName  if true then entities are looked up exclusively using displayname, otherwise forename and surname fields are used [default=false]
  *                transaction - if Transaction instance is passed, use it for all Db-related tasks [default=null]
  *                returnInstance = return ca_entities instance rather than entity_id. Default is false.
  *                generateIdnoWithTemplate = A template to use when setting the idno. The template is a value with automatically-set SERIAL values replaced with % characters. Eg. 2012.% will set the created row's idno value to 2012.121 (assuming that 121 is the next number in the serial sequence.) The template is NOT used if idno is passed explicitly as a value in $pa_values.
  *                importEvent = if ca_data_import_events instance is passed then the insert/update of the entity will be logged as part of the import
  *                importEventSource = if importEvent is passed, then the value set for importEventSource is used in the import event log as the data source. If omitted a default value of "?" is used
  *                nonPreferredLabels = an optional array of nonpreferred labels to add to any newly created entities. Each label in the array is an array with required entity label values.
  *				  forceUpdate = update attributes set in $pa_values even if row already exists. [Default=false; no values are updated in existing rows]
  *				  matchMediaFilesWithoutExtension = For ca_object_representations, if media path is invalid, attempt to find media in referenced directory and sub-directories that has a matching name, regardless of file extension. [default=false] 
  *                log = if KLogger instance is passed then actions will be logged
  *				  ignoreParent = Don't take into account parent_id value when looking for matching rows [Default is false]
  * @return bool|BaseModel|mixed|null
  */
 private static function _getID($ps_table, $pa_label, $pn_parent_id, $pn_type_id, $pn_locale_id, $pa_values = null, $pa_options = null)
 {
     if (!is_array($pa_options)) {
         $pa_options = array();
     }
     $o_dm = Datamodel::load();
     /** @var KLogger $o_log */
     $o_log = isset($pa_options['log']) && $pa_options['log'] instanceof KLogger ? $pa_options['log'] : null;
     if (!($t_instance = $o_dm->getInstanceByTableName($ps_table, true))) {
         return null;
     }
     $vs_table_display_name = $t_instance->getProperty('NAME_SINGULAR');
     $vs_table_class = $t_instance->tableName();
     $vs_label_display_fld = $t_instance->getLabelDisplayField();
     $vs_label = $pa_label[$vs_label_display_fld];
     $pb_output_errors = caGetOption('outputErrors', $pa_options, false);
     $pb_match_on_displayname = caGetOption('matchOnDisplayName', $pa_options, false);
     $pa_match_on = caGetOption('matchOn', $pa_options, array('label', 'idno', 'displayname'), array('castTo' => "array"));
     $ps_event_source = caGetOption('importEventSource', $pa_options, '?');
     $pb_match_media_without_ext = caGetOption('matchMediaFilesWithoutExtension', $pa_options, false);
     $pb_ignore_parent = caGetOption('ignoreParent', $pa_options, false);
     $vn_parent_id = $pn_parent_id ? $pn_parent_id : caGetOption('parent_id', $pa_values, null);
     if (!$vn_parent_id) {
         $vn_parent_id = null;
     }
     $vs_idno_fld = $t_instance->getProperty('ID_NUMBERING_ID_FIELD');
     $vs_idno = caGetOption($vs_idno_fld, $pa_values, null);
     /** @var ca_data_import_events $o_event */
     $o_event = isset($pa_options['importEvent']) && $pa_options['importEvent'] instanceof ca_data_import_events ? $pa_options['importEvent'] : null;
     if (isset($pa_options['transaction']) && $pa_options['transaction'] instanceof Transaction) {
         $t_instance->setTransaction($pa_options['transaction']);
         if ($o_event) {
             $o_event->setTransaction($pa_options['transaction']);
         }
     }
     if (preg_match('!\\%!', $vs_idno)) {
         $pa_options['generateIdnoWithTemplate'] = $vs_idno;
         $vs_idno = null;
     }
     if (!$vs_idno) {
         if (isset($pa_options['generateIdnoWithTemplate']) && $pa_options['generateIdnoWithTemplate']) {
             $pa_values[$vs_idno_fld] = $vs_idno = $t_instance->setIdnoWithTemplate($pa_options['generateIdnoWithTemplate'], array('dontSetValue' => true));
         }
     }
     $va_regex_list = $va_replacements_list = null;
     if ($vs_table_class == 'ca_object_representations') {
         // Get list of regular expressions that user can use to transform file names to match object idnos
         $va_regex_list = caBatchGetMediaFilenameToIdnoRegexList(array('log' => $o_log));
         // Get list of replacements that user can use to transform file names to match object idnos
         $va_replacements_list = caBatchGetMediaFilenameReplacementRegexList(array('log' => $o_log));
     }
     $vn_id = null;
     foreach ($pa_match_on as $vs_match_on) {
         switch (strtolower($vs_match_on)) {
             case 'idno':
                 if ($vs_idno == '%') {
                     break;
                 }
                 // don't try to match on an unreplaced idno placeholder
                 switch ($vs_table_class) {
                     case 'ca_object_representations':
                         //
                         // idno lookups for representations use media batch importer rules
                         //
                         $va_idnos_to_match = array($vs_idno);
                         if (is_array($va_replacements_list)) {
                             foreach ($va_replacements_list as $vs_replacement_code => $va_replacement) {
                                 if (isset($va_replacement['search']) && is_array($va_replacement['search'])) {
                                     $va_replace = caGetOption('replace', $va_replacement);
                                     $va_search = array();
                                     foreach ($va_replacement['search'] as $vs_search) {
                                         $va_search[] = '!' . $vs_search . '!';
                                     }
                                     if ($vs_idno_proc = @preg_replace($va_search, $va_replace, $vs_idno)) {
                                         $va_idnos_to_match[] = $vs_idno_proc;
                                     }
                                 }
                             }
                         }
                         if (is_array($va_regex_list) && sizeof($va_regex_list)) {
                             foreach ($va_regex_list as $vs_regex_name => $va_regex_info) {
                                 foreach ($va_regex_info['regexes'] as $vs_regex) {
                                     foreach ($va_idnos_to_match as $vs_idno_match) {
                                         if (!$vs_idno_match) {
                                             continue;
                                         }
                                         if (preg_match('!' . $vs_regex . '!', $vs_idno_match, $va_matches)) {
                                             if ($vn_id = ca_object_representations::find(array('idno' => $va_matches[1]), array('returnAs' => 'firstId', 'purifyWithFallback' => true, 'transaction' => $pa_options['transaction']))) {
                                                 break 5;
                                             }
                                         }
                                     }
                                 }
                             }
                         } else {
                             foreach ($va_idnos_to_match as $vs_idno_match) {
                                 if (!$vs_idno_match) {
                                     continue;
                                 }
                                 if ($vn_id = ca_object_representations::find(array('idno' => $vs_idno_match), array('returnAs' => 'firstId', 'purifyWithFallback' => true, 'transaction' => $pa_options['transaction']))) {
                                     break 3;
                                 }
                             }
                         }
                         break;
                     default:
                         //
                         // Standard idno lookup for most tables
                         //
                         $va_find_vals = array($vs_idno_fld => $vs_idno ? $vs_idno : ($pa_label['_originalText'] ? $pa_label['_originalText'] : $vs_label), 'type_id' => $pn_type_id);
                         if (!$pb_ignore_parent && isset($pa_values['parent_id'])) {
                             $va_find_vals['parent_id'] = $pa_values['parent_id'];
                         }
                         if (($vs_idno || trim($pa_label['_originalText'] || $vs_label)) && ($vn_id = $vs_table_class::find($va_find_vals, array('returnAs' => 'firstId', 'purifyWithFallback' => true, 'transaction' => $pa_options['transaction'])))) {
                             break 2;
                         }
                         break;
                 }
                 break;
             case 'label':
             case 'labels':
                 if ($pb_match_on_displayname && strlen(trim($pa_label['displayname'])) > 0) {
                     // entities only
                     $va_params = array('preferred_labels' => array('displayname' => $pa_label['displayname']), 'type_id' => $pn_type_id);
                     if (!$pb_ignore_parent && isset($pa_values['parent_id'])) {
                         $va_params['parent_id'] = $vn_parent_id;
                     }
                     $vn_id = $vs_table_class::find($va_params, array('returnAs' => 'firstId', 'purifyWithFallback' => true, 'transaction' => $pa_options['transaction']));
                 } elseif ($vs_table_class == 'ca_entities') {
                     // entities only
                     $va_params = array('preferred_labels' => array('forename' => $pa_label['forename'], 'middlename' => $pa_label['middlename'], 'surname' => $pa_label['surname']), 'type_id' => $pn_type_id);
                     if (!$pb_ignore_parent) {
                         $va_params['parent_id'] = $vn_parent_id;
                     }
                     $vn_id = $vs_table_class::find($va_params, array('returnAs' => 'firstId', 'purifyWithFallback' => true, 'transaction' => $pa_options['transaction']));
                 } else {
                     $va_params = array('preferred_labels' => array($vs_label_display_fld => $pa_label[$vs_label_display_fld]), 'type_id' => $pn_type_id);
                     if (!$pb_ignore_parent && isset($pa_values['parent_id'])) {
                         $va_params['parent_id'] = $vn_parent_id;
                     }
                     $vn_id = $vs_table_class::find($va_params, array('returnAs' => 'firstId', 'purifyWithFallback' => true, 'transaction' => $pa_options['transaction']));
                 }
                 if ($vn_id) {
                     break 2;
                 }
                 break;
                 //
                 // For entities only
                 //
             //
             // For entities only
             //
             case 'surname':
                 $va_params = array('preferred_labels' => array('surname' => $pa_label['surname']), 'type_id' => $pn_type_id);
                 if (!$pb_ignore_parent && isset($pa_values['parent_id'])) {
                     $va_params['parent_id'] = $vn_parent_id;
                 }
                 $vn_id = $vs_table_class::find($va_params, array('returnAs' => 'firstId', 'purifyWithFallback' => true, 'transaction' => $pa_options['transaction']));
                 if ($vn_id) {
                     break 2;
                 }
                 break;
             case 'forename':
                 $va_params = array('preferred_labels' => array('forename' => $pa_label['forename']), 'type_id' => $pn_type_id);
                 if (!$pb_ignore_parent && isset($pa_values['parent_id'])) {
                     $va_params['parent_id'] = $vn_parent_id;
                 }
                 $vn_id = $vs_table_class::find($va_params, array('returnAs' => 'firstId', 'purifyWithFallback' => true, 'transaction' => $pa_options['transaction']));
                 if ($vn_id) {
                     break 2;
                 }
                 break;
             case 'displayname':
                 $va_params = array('preferred_labels' => array('displayname' => $pa_label['displayname']), 'type_id' => $pn_type_id);
                 if (!$pb_ignore_parent && isset($pa_values['parent_id'])) {
                     $va_params['parent_id'] = $vn_parent_id;
                 }
                 $vn_id = $vs_table_class::find($va_params, array('returnAs' => 'firstId', 'purifyWithFallback' => true, 'transaction' => $pa_options['transaction']));
                 if ($vn_id) {
                     break 2;
                 }
                 break;
         }
     }
     if (!$vn_id) {
         //
         // Create new row
         //
         if (caGetOption('dontCreate', $pa_options, false)) {
             return false;
         }
         if ($o_event) {
             $o_event->beginItem($ps_event_source, $vs_table_class, 'I');
         }
         // If we're creating a new item, it's probably a good idea to *NOT* use a
         // BaseModel instance from cache, because those cannot change their type_id
         if (!($t_instance = $o_dm->getInstanceByTableName($ps_table, false))) {
             return null;
         }
         if (isset($pa_options['transaction']) && $pa_options['transaction'] instanceof Transaction) {
             $t_instance->setTransaction($pa_options['transaction']);
         }
         $t_instance->setMode(ACCESS_WRITE);
         $t_instance->set('locale_id', $pn_locale_id);
         $t_instance->set('type_id', $pn_type_id);
         $va_intrinsics = array('source_id' => null, 'access' => 0, 'status' => 0, 'lifespan' => null, 'parent_id' => $vn_parent_id, 'lot_status_id' => null, '_interstitial' => null);
         if ($vs_hier_id_fld = $t_instance->getProperty('HIERARCHY_ID_FLD')) {
             $va_intrinsics[$vs_hier_id_fld] = null;
         }
         if ($vs_idno_fld) {
             $va_intrinsics[$vs_idno_fld] = $vs_idno ? $vs_idno : null;
         }
         foreach ($va_intrinsics as $vs_fld => $vm_fld_default) {
             if ($t_instance->hasField($vs_fld)) {
                 $t_instance->set($vs_fld, caGetOption($vs_fld, $pa_values, $vm_fld_default));
             }
             unset($pa_values[$vs_fld]);
         }
         if ($t_instance->hasField('media') && $t_instance->getFieldInfo('media', 'FIELD_TYPE') == FT_MEDIA && isset($pa_values['media']) && $pa_values['media']) {
             if (is_array($pa_values['media'])) {
                 $pa_values['media'] = array_shift($pa_values['media']);
             }
             if ($pb_match_media_without_ext && !isURL($pa_values['media']) && !file_exists($pa_values['media'])) {
                 $vs_dirname = pathinfo($pa_values['media'], PATHINFO_DIRNAME);
                 $vs_filename = preg_replace('!\\.[A-Za-z0-9]{1,4}$!', '', pathinfo($pa_values['media'], PATHINFO_BASENAME));
                 $vs_original_path = $pa_values['media'];
                 $pa_values['media'] = null;
                 $va_files_in_dir = caGetDirectoryContentsAsList($vs_dirname, true, false, false, false);
                 foreach ($va_files_in_dir as $vs_filepath) {
                     if ($o_log) {
                         $o_log->logDebug(_t("Trying media %1 in place of %2/%3", $vs_filepath, $vs_original_path, $vs_filename));
                     }
                     if (pathinfo($vs_filepath, PATHINFO_FILENAME) == $vs_filename) {
                         if ($o_log) {
                             $o_log->logNotice(_t("Found media %1 for %2/%3", $vs_filepath, $vs_original_path, $vs_filename));
                         }
                         $pa_values['media'] = $vs_filepath;
                         break;
                     }
                 }
             }
             $t_instance->set('media', $pa_values['media']);
         }
         $t_instance->insert();
         if ($t_instance->numErrors()) {
             if ($pb_output_errors) {
                 print "[Error] " . _t("Could not insert %1 %2: %3", $vs_table_display_name, $pa_label[$vs_label_display_fld], join('; ', $t_instance->getErrors())) . "\n";
             }
             if ($o_log) {
                 $o_log->logError(_t("Could not insert %1 %2: %3", $vs_table_display_name, $pa_label[$vs_label_display_fld], join('; ', $t_instance->getErrors())));
             }
             return null;
         }
         $vb_label_errors = false;
         $t_instance->addLabel($pa_label, $pn_locale_id, null, true);
         if ($t_instance->numErrors()) {
             if ($pb_output_errors) {
                 print "[Error] " . _t("Could not set preferred label for %1 %2: %3", $vs_table_display_name, $pa_label[$vs_label_display_fld], join('; ', $t_instance->getErrors())) . "\n";
             }
             if ($o_log) {
                 $o_log->logError(_t("Could not set preferred label for %1 %2: %3", $vs_table_display_name, $pa_label[$vs_label_display_fld], join('; ', $t_instance->getErrors())));
             }
             $vb_label_errors = true;
         }
         DataMigrationUtils::_setIdno($t_instance, $vs_idno, $pa_options);
         $vb_attr_errors = !DataMigrationUtils::_setAttributes($t_instance, $pn_locale_id, $pa_values, $pa_options);
         DataMigrationUtils::_setNonPreferredLabels($t_instance, $pn_locale_id, $pa_options);
         $vn_id = $t_instance->getPrimaryKey();
         if ($o_event) {
             if ($vb_attr_errors || $vb_label_errors) {
                 $o_event->endItem($vn_id, __CA_DATA_IMPORT_ITEM_PARTIAL_SUCCESS__, _t("Errors setting field values: %1", join('; ', $t_instance->getErrors())));
             } else {
                 $o_event->endItem($vn_id, __CA_DATA_IMPORT_ITEM_SUCCESS__, '');
             }
         }
         if ($o_log) {
             $o_log->logInfo(_t("Created new %1 %2", $vs_table_display_name, $pa_label[$vs_label_display_fld]));
         }
         if (isset($pa_options['returnInstance']) && $pa_options['returnInstance']) {
             return $t_instance;
         }
     } else {
         if ($o_event) {
             $o_event->beginItem($ps_event_source, $vs_table_class, 'U');
         }
         if ($o_log) {
             $o_log->logDebug(_t("Found existing %1 %2 in DataMigrationUtils::_getID()", $vs_table_display_name, $pa_label[$vs_label_display_fld]));
         }
         $vb_attr_errors = false;
         if (($vb_force_update = caGetOption('forceUpdate', $pa_options, false)) || ($vb_return_instance = caGetOption('returnInstance', $pa_options, false))) {
             if (!($t_instance = $o_dm->getInstanceByTableName($vs_table_class, false))) {
                 return null;
             }
             if (isset($pa_options['transaction']) && $pa_options['transaction'] instanceof Transaction) {
                 $t_instance->setTransaction($pa_options['transaction']);
             }
             $vb_has_attr = false;
             if ($vb_force_update) {
                 foreach ($pa_values as $vs_element => $va_values) {
                     if ($t_instance->hasElement($vs_element)) {
                         $vb_has_attr = true;
                         break;
                     }
                 }
             }
             if ($vb_return_instance || $vb_force_update && $vb_has_attr) {
                 $vn_rc = $t_instance->load($vn_id);
             } else {
                 $vn_rc = true;
             }
             if (!$vn_rc) {
                 if ($o_log) {
                     $o_log->logError(_t("Could not load existing %1 with id %2 (%3) in DataMigrationUtils::_getID() [THIS SHOULD NOT HAPPEN]", $vs_table_display_name, $vn_id, $pa_label[$vs_label_display_fld]));
                 }
                 return null;
             } else {
                 if ($vb_force_update && $vb_has_attr) {
                     if ($vb_attr_errors = !DataMigrationUtils::_setAttributes($t_instance, $pn_locale_id, $pa_values, $pa_options)) {
                         if ($o_log) {
                             $o_log->logError(_t("Could not set attributes for %1 with id %2 (%3) in DataMigrationUtils::_getID(): %4", $vs_table_display_name, $vn_id, $pa_label[$vs_label_display_fld], join("; ", $t_instance->getErrors())));
                         }
                     }
                 }
                 if ($o_event) {
                     if ($vb_attr_errors) {
                         $o_event->endItem($vn_id, __CA_DATA_IMPORT_ITEM_PARTIAL_SUCCESS__, _t("Errors setting field values: %1", join('; ', $t_instance->getErrors())));
                     } else {
                         $o_event->endItem($vn_id, __CA_DATA_IMPORT_ITEM_SUCCESS__, '');
                     }
                 }
                 if ($vb_return_instance) {
                     return $t_instance;
                 }
             }
         }
         if ($o_event) {
             $o_event->endItem($vn_id, __CA_DATA_IMPORT_ITEM_SUCCESS__, '');
         }
     }
     return $vn_id;
 }
Example #7
0
 /**
  * Fix file permissions
  */
 public static function fix_permissions($po_opts = null)
 {
     // Guess web server user
     if (!($vs_user = $po_opts->getOption("user"))) {
         $vs_user = caDetermineWebServerUser();
         if (!$po_opts->getOption("quiet") && $vs_user) {
             CLIUtils::addMessage(_t("Determined web server user to be \"%1\"", $vs_user));
         }
     }
     if (!$vs_user) {
         $vs_user = caGetProcessUserName();
         CLIUtils::addError(_t("Cannot determine web server user. Using %1 instead.", $vs_user));
     }
     if (!$vs_user) {
         CLIUtils::addError(_t("Cannot determine the user. Please specify one with the --user option."));
         return false;
     }
     if (!($vs_group = $po_opts->getOption("group"))) {
         $vs_group = caGetProcessGroupName();
         if (!$po_opts->getOption("quiet") && $vs_group) {
             CLIUtils::addMessage(_t("Determined web server group to be \"%1\"", $vs_group));
         }
     }
     if (!$vs_group) {
         CLIUtils::addError(_t("Cannot determine the group. Please specify one with the --group option."));
         return false;
     }
     if (!$po_opts->getOption("quiet")) {
         CLIUtils::addMessage(_t("Fixing permissions for the temporary directory (app/tmp) for ownership by \"%1\"...", $vs_user));
     }
     $va_files = caGetDirectoryContentsAsList($vs_path = __CA_APP_DIR__ . '/tmp', true, false, false, true);
     foreach ($va_files as $vs_path) {
         chown($vs_path, $vs_user);
         chgrp($vs_path, $vs_group);
         chmod($vs_path, 0770);
     }
     if (!$po_opts->getOption("quiet")) {
         CLIUtils::addMessage(_t("Fixing permissions for the media directory (media) for ownership by \"%1\"...", $vs_user));
     }
     $va_files = caGetDirectoryContentsAsList($vs_path = __CA_BASE_DIR__ . '/media', true, false, false, true);
     foreach ($va_files as $vs_path) {
         chown($vs_path, $vs_user);
         chgrp($vs_path, $vs_group);
         chmod($vs_path, 0775);
     }
     if (!$po_opts->getOption("quiet")) {
         CLIUtils::addMessage(_t("Fixing permissions for the HTMLPurifier definition cache directory (app/lib/core/Parsers/htmlpurifier/standalone/HTMLPurifier/DefinitionCache) for ownership by \"%1\"...", $vs_user));
     }
     $va_files = caGetDirectoryContentsAsList($vs_path = __CA_LIB_DIR__ . '/core/Parsers/htmlpurifier/standalone/HTMLPurifier/DefinitionCache', true, false, false, true);
     foreach ($va_files as $vs_path) {
         chown($vs_path, $vs_user);
         chgrp($vs_path, $vs_group);
         chmod($vs_path, 0770);
     }
     return true;
 }
Example #8
0
function caZipDirectory($ps_directory, $ps_name, $ps_output_file)
{
    $va_files_to_zip = caGetDirectoryContentsAsList($ps_directory);
    $vs_tmp_name = caGetTempFileName('caZipDirectory', 'zip');
    $o_phar = new PharData($vs_tmp_name, null, null, Phar::ZIP);
    foreach ($va_files_to_zip as $vs_file) {
        $vs_name = str_replace($ps_directory, $ps_name, $vs_file);
        $o_phar->addFile($vs_file, $vs_name);
    }
    copy($vs_tmp_name, $ps_output_file);
    unlink($vs_tmp_name);
    return true;
}
Example #9
0
function caZipDirectory($ps_directory, $ps_name, $ps_output_file)
{
    $va_files_to_zip = caGetDirectoryContentsAsList($ps_directory);
    $o_zip = new ZipFile();
    foreach ($va_files_to_zip as $vs_file) {
        $vs_name = str_replace($ps_directory, $ps_name, $vs_file);
        $o_zip->addFile($vs_file, $vs_name);
    }
    $vs_new_file = $o_zip->output(ZIPFILE_FILEPATH);
    copy($vs_new_file, $ps_output_file);
    unlink($vs_new_file);
    return true;
}
Example #10
0
 /**
  * Returns representation_id for the object representation with the specified name (and type) or idno (regardless of specified type.) If the object does
  * not already exist then it will be created with the specified name, type and locale, as well as with any specified values in the $pa_values array.
  * $pa_values keys should be either valid object fields or attributes.
  *
  * @param string $ps_representation_name Object label name
  * @param int $pn_type_id The type_id of the object type to use if the representation needs to be created
  * @param int $pn_locale_id The locale_id to use if the representation needs to be created (will be used for both the object locale as well as the label locale)
  * @param array $pa_values An optional array of additional values to populate newly created representation records with. These values are *only* used for newly created representation; they will not be applied if the representation named already exists. The array keys should be names of ca_object_representations fields or valid representation attributes. Values should be either a scalar (for single-value attributes) or an array of values for (multi-valued attributes)
  * @param array $pa_options An optional array of options, which include:
  *                outputErrors - if true, errors will be printed to console [default=false]
  *                matchOn = optional list indicating sequence of checks for an existing record; values of array can be "label" and "idno". Ex. array("idno", "label") will first try to match on idno and then label if the first match fails.
  *                dontCreate - if true then new representations will not be created [default=false]
  *                transaction - if Transaction object is passed, use it for all Db-related tasks [default=null]
  *                returnInstance = return ca_object_representations instance rather than representation_id. Default is false.
  *                generateIdnoWithTemplate = A template to use when setting the idno. The template is a value with automatically-set SERIAL values replaced with % characters. Eg. 2012.% will set the created row's idno value to 2012.121 (assuming that 121 is the next number in the serial sequence.) The template is NOT used if idno is passed explicitly as a value in $pa_values.
  *                importEvent = if ca_data_import_events instance is passed then the insert/update of the representation will be logged as part of the import
  *                importEventSource = if importEvent is passed, then the value set for importEventSource is used in the import event log as the data source. If omitted a default value of "?" is used
  *                nonPreferredLabels = an optional array of nonpreferred labels to add to any newly created representations. Each label in the array is an array with required representation label values.
  *                log = if KLogger instance is passed then actions will be logged
  *				  matchMediaFilesWithoutExtension = if media path is invalid, attempt to find media in referenced directory and sub-directories that has a matching name, regardless of file extension. [default=false] 
  * @return bool|ca_object_representations|mixed|null
  */
 static function getObjectRepresentationID($ps_representation_name, $pn_type_id, $pn_locale_id, $pa_values = null, $pa_options = null)
 {
     if (!is_array($pa_options)) {
         $pa_options = array();
     }
     if (!isset($pa_options['outputErrors'])) {
         $pa_options['outputErrors'] = false;
     }
     $vb_match_media_without_extension = caGetOption('matchMediaFilesWithoutExtension', $pa_options, false);
     $pa_match_on = caGetOption('matchOn', $pa_options, array('label', 'idno'), array('castTo' => "array"));
     /** @var ca_data_import_events $o_event */
     $o_event = isset($pa_options['importEvent']) && $pa_options['importEvent'] instanceof ca_data_import_events ? $pa_options['importEvent'] : null;
     $t_rep = new ca_object_representations();
     if (isset($pa_options['transaction']) && $pa_options['transaction'] instanceof Transaction) {
         $t_rep->setTransaction($pa_options['transaction']);
         if ($o_event) {
             $o_event->setTransaction($pa_options['transaction']);
         }
     }
     $vs_event_source = isset($pa_options['importEventSource']) && $pa_options['importEventSource'] ? $pa_options['importEventSource'] : "?";
     /** @var KLogger $o_log */
     $o_log = isset($pa_options['log']) && $pa_options['log'] instanceof KLogger ? $pa_options['log'] : null;
     $vs_idno = isset($pa_values['idno']) ? (string) $pa_values['idno'] : null;
     if (preg_match('!\\%!', $vs_idno)) {
         $pa_options['generateIdnoWithTemplate'] = $vs_idno;
         $vs_idno = null;
     }
     if (!$vs_idno) {
         if (isset($pa_options['generateIdnoWithTemplate']) && $pa_options['generateIdnoWithTemplate']) {
             $vs_idno = $t_rep->setIdnoWithTemplate($pa_options['generateIdnoWithTemplate'], array('dontSetValue' => true));
         }
     }
     $va_regex_list = caBatchGetMediaFilenameToIdnoRegexList(array('log' => $o_log));
     // Get list of replacements that user can use to transform file names to match object idnos
     $va_replacements_list = caBatchGetMediaFilenameReplacementRegexList(array('log' => $o_log));
     $vn_id = null;
     foreach ($pa_match_on as $vs_match_on) {
         switch (strtolower($vs_match_on)) {
             case 'label':
             case 'labels':
                 if (trim($ps_representation_name)) {
                     if ($vn_id = ca_object_representations::find(array('preferred_labels' => array('name' => $ps_representation_name), 'type_id' => $pn_type_id), array('returnAs' => 'firstId', 'transaction' => $pa_options['transaction']))) {
                         break 2;
                     }
                 }
                 break;
             case 'idno':
                 if (!$vs_idno) {
                     break;
                 }
                 if ($vs_idno == '%') {
                     break;
                 }
                 // don't try to match on an unreplaced idno placeholder
                 $va_idnos_to_match = array($vs_idno);
                 if (is_array($va_replacements_list)) {
                     foreach ($va_replacements_list as $vs_replacement_code => $va_replacement) {
                         if (isset($va_replacement['search']) && is_array($va_replacement['search'])) {
                             $va_replace = caGetOption('replace', $va_replacement);
                             $va_search = array();
                             foreach ($va_replacement['search'] as $vs_search) {
                                 $va_search[] = '!' . $vs_search . '!';
                             }
                             if ($vs_idno_proc = @preg_replace($va_search, $va_replace, $vs_idno)) {
                                 $va_idnos_to_match[] = $vs_idno_proc;
                             }
                         }
                     }
                 }
                 if (is_array($va_regex_list) && sizeof($va_regex_list)) {
                     foreach ($va_regex_list as $vs_regex_name => $va_regex_info) {
                         foreach ($va_regex_info['regexes'] as $vs_regex) {
                             foreach ($va_idnos_to_match as $vs_idno_match) {
                                 if (!$vs_idno_match) {
                                     continue;
                                 }
                                 if (preg_match('!' . $vs_regex . '!', $vs_idno_match, $va_matches)) {
                                     if ($vn_id = ca_object_representations::find(array('idno' => $va_matches[1]), array('returnAs' => 'firstId', 'transaction' => $pa_options['transaction']))) {
                                         break 5;
                                     }
                                 }
                             }
                         }
                     }
                 } else {
                     foreach ($va_idnos_to_match as $vs_idno_match) {
                         if (!$vs_idno_match) {
                             continue;
                         }
                         if ($vn_id = ca_object_representations::find(array('idno' => $vs_idno_match), array('returnAs' => 'firstId', 'transaction' => $pa_options['transaction']))) {
                             break 3;
                         }
                     }
                 }
                 break;
         }
     }
     if (!$vn_id) {
         if (isset($pa_options['dontCreate']) && $pa_options['dontCreate']) {
             return false;
         }
         if ($o_event) {
             $o_event->beginItem($vs_event_source, 'ca_object_representations', 'I');
         }
         $t_rep->setMode(ACCESS_WRITE);
         $t_rep->set('locale_id', $pn_locale_id);
         $t_rep->set('type_id', $pn_type_id);
         $t_rep->set('source_id', isset($pa_values['source_id']) ? $pa_values['source_id'] : null);
         $t_rep->set('access', isset($pa_values['access']) ? $pa_values['access'] : 0);
         $t_rep->set('status', isset($pa_values['status']) ? $pa_values['status'] : 0);
         if (isset($pa_values['media']) && $pa_values['media']) {
             if ($vb_match_media_without_extension && !isURL($pa_values['media']) && !file_exists($pa_values['media'])) {
                 $vs_dirname = pathinfo($pa_values['media'], PATHINFO_DIRNAME);
                 $vs_filename = preg_replace('!\\.[A-Za-z0-9]{1,4}$!', '', pathinfo($pa_values['media'], PATHINFO_BASENAME));
                 $vs_original_path = $pa_values['media'];
                 $pa_values['media'] = null;
                 $va_files_in_dir = caGetDirectoryContentsAsList($vs_dirname, true, false, false, false);
                 foreach ($va_files_in_dir as $vs_filepath) {
                     if ($o_log) {
                         $o_log->logDebug(_t("Trying media %1 in place of %2/%3", $vs_filepath, $vs_original_path, $vs_filename));
                     }
                     if (pathinfo($vs_filepath, PATHINFO_FILENAME) == $vs_filename) {
                         if ($o_log) {
                             $o_log->logNotice(_t("Found media %1 for %2/%3", $vs_filepath, $vs_original_path, $vs_filename));
                         }
                         $pa_values['media'] = $vs_filepath;
                         break;
                     }
                 }
             }
             $t_rep->set('media', $pa_values['media']);
         }
         $t_rep->set('idno', $vs_idno);
         $t_rep->insert();
         if ($t_rep->numErrors()) {
             if (isset($pa_options['outputErrors']) && $pa_options['outputErrors']) {
                 print "[Error] " . _t("Could not insert object %1: %2", $ps_representation_name, join('; ', $t_rep->getErrors())) . "\n";
             }
             if ($o_log) {
                 $o_log->logError(_t("Could not insert object %1: %2", $ps_representation_name, join('; ', $t_rep->getErrors())));
             }
             return null;
         }
         $vb_label_errors = false;
         $t_rep->addLabel(array('name' => $ps_representation_name), $pn_locale_id, null, true);
         if ($t_rep->numErrors()) {
             if (isset($pa_options['outputErrors']) && $pa_options['outputErrors']) {
                 print "[Error] " . _t("Could not set preferred label for object %1: %2", $ps_representation_name, join('; ', $t_rep->getErrors())) . "\n";
             }
             if ($o_log) {
                 $o_log->logError(_t("Could not set preferred label for object %1: %2", $ps_representation_name, join('; ', $t_rep->getErrors())));
             }
             $vb_label_errors = true;
         }
         /** @var IIDNumbering $o_idno */
         if ($o_idno = $t_rep->getIDNoPlugInInstance()) {
             $va_values = $o_idno->htmlFormValuesAsArray('idno', $vs_idno);
             if (!is_array($va_values)) {
                 $va_values = array($va_values);
             }
             if (!($vs_sep = $o_idno->getSeparator())) {
                 $vs_sep = '';
             }
             if (($vs_proc_idno = join($vs_sep, $va_values)) && $vs_proc_idno != $vs_idno) {
                 $t_rep->set('idno', $vs_proc_idno);
                 $t_rep->update();
                 if ($t_rep->numErrors()) {
                     if (isset($pa_options['outputErrors']) && $pa_options['outputErrors']) {
                         print "[Error] " . _t("Could not update idno for %1: %2", $ps_representation_name, join('; ', $t_rep->getErrors())) . "\n";
                     }
                     if ($o_log) {
                         $o_log->logError(_t("Could not object idno for %1: %2", $ps_representation_name, join('; ', $t_rep->getErrors())));
                     }
                     return null;
                 }
             }
         }
         unset($pa_values['access']);
         unset($pa_values['status']);
         unset($pa_values['idno']);
         unset($pa_values['source_id']);
         $vb_attr_errors = false;
         if (is_array($pa_values)) {
             foreach ($pa_values as $vs_element => $va_values) {
                 if (!caIsIndexedArray($va_values)) {
                     $va_values = array($va_values);
                 }
                 foreach ($va_values as $va_value) {
                     if (is_array($va_value)) {
                         // array of values (complex multi-valued attribute)
                         $t_rep->addAttribute(array_merge($va_value, array('locale_id' => $pn_locale_id)), $vs_element);
                     } else {
                         // scalar value (simple single value attribute)
                         if ($va_value) {
                             $t_rep->addAttribute(array('locale_id' => $pn_locale_id, $vs_element => $va_value), $vs_element);
                         }
                     }
                 }
             }
             $t_rep->update();
             if ($t_rep->numErrors()) {
                 if (isset($pa_options['outputErrors']) && $pa_options['outputErrors']) {
                     print "[Error] " . _t("Could not set values for representation %1: %2", $ps_representation_name, join('; ', $t_rep->getErrors())) . "\n";
                 }
                 if ($o_log) {
                     $o_log->logError(_t("Could not set values for representation %1: %2", $ps_representation_name, join('; ', $t_rep->getErrors())));
                 }
                 $vb_attr_errors = true;
             }
         }
         if (is_array($va_nonpreferred_labels = caGetOption("nonPreferredLabels", $pa_options, null))) {
             if (caIsAssociativeArray($va_nonpreferred_labels)) {
                 // single non-preferred label
                 $va_labels = array($va_nonpreferred_labels);
             } else {
                 // list of non-preferred labels
                 $va_labels = $va_nonpreferred_labels;
             }
             foreach ($va_labels as $va_label) {
                 $t_rep->addLabel($va_label, $pn_locale_id, null, false);
                 if ($t_rep->numErrors()) {
                     if (isset($pa_options['outputErrors']) && $pa_options['outputErrors']) {
                         print "[Error] " . _t("Could not set non-preferred label for representation %1: %2", $ps_representation_name, join('; ', $t_rep->getErrors())) . "\n";
                     }
                     if ($o_log) {
                         $o_log->logError(_t("Could not set non-preferred label for representation %1: %2", $ps_representation_name, join('; ', $t_rep->getErrors())));
                     }
                 }
             }
         }
         $vn_representation_id = $t_rep->getPrimaryKey();
         if ($o_event) {
             if ($vb_attr_errors || $vb_label_errors) {
                 $o_event->endItem($vn_representation_id, __CA_DATA_IMPORT_ITEM_PARTIAL_SUCCESS__, _t("Errors setting field values: %1", join('; ', $t_rep->getErrors())));
             } else {
                 $o_event->endItem($vn_representation_id, __CA_DATA_IMPORT_ITEM_SUCCESS__, '');
             }
         }
         if ($o_log) {
             $o_log->logInfo(_t("Created new representation %1", $ps_representation_name));
         }
         if (isset($pa_options['returnInstance']) && $pa_options['returnInstance']) {
             return $t_rep;
         }
     } else {
         if ($o_event) {
             $o_event->beginItem($vs_event_source, 'ca_object_representations', 'U');
         }
         $vn_representation_id = $vn_id;
         if ($o_event) {
             $o_event->endItem($vn_representation_id, __CA_DATA_IMPORT_ITEM_SUCCESS__, '');
         }
         if ($o_log) {
             $o_log->logDebug(_t("Found existing representation %1 in DataMigrationUtils::getObjectRepresentationID()", $ps_representation_name));
         }
         if (isset($pa_options['returnInstance']) && $pa_options['returnInstance']) {
             $t_rep = new ca_object_representations($vn_representation_id);
             if (isset($pa_options['transaction']) && $pa_options['transaction'] instanceof Transaction) {
                 $t_rep->setTransaction($pa_options['transaction']);
             }
             return $t_rep;
         }
     }
     return $vn_representation_id;
 }
 /**
  * Import metadata using a mapping
  *
  * @param RequestHTTP $po_request The current request
  * @param string $ps_source A path to a file or directory of files to import
  * @param string $ps_importer The code of the importer (mapping) to use
  * @param string $ps_input_format The format of the source data
  * @param array $pa_options
  *		progressCallback =
  *		reportCallback = 
  *		sendMail = 
  *		dryRun = 
  *		importAllDatasets = 
  *		log = log directory path
  *		logLevel = KLogger constant for minimum log level to record. Default is KLogger::INFO. Constants are, in descending order of shrillness:
  *			KLogger::EMERG = Emergency messages (system is unusable)
  *			KLogger::ALERT = Alert messages (action must be taken immediately)
  *			KLogger::CRIT = Critical conditions
  *			KLogger::ERR = Error conditions
  *			KLogger::WARN = Warnings
  *			KLogger::NOTICE = Notices (normal but significant conditions)
  *			KLogger::INFO = Informational messages
  *			KLogger::DEBUG = Debugging messages
  */
 public static function importMetadata($po_request, $ps_source, $ps_importer, $ps_input_format, $pa_options = null)
 {
     $va_errors = $va_noticed = array();
     $vn_start_time = time();
     $o_config = Configuration::load();
     if (!ca_data_importers::mappingExists($ps_importer)) {
         $va_errors['general'] = array('idno' => "*", 'label' => "*", 'errors' => array(_t('Importer %1 does not exist', $ps_importer)), 'status' => 'ERROR');
         return false;
     }
     $vs_log_dir = caGetOption('log', $pa_options, null);
     $vs_log_level = caGetOption('logLevel', $pa_options, "INFO");
     $vb_import_all_datasets = caGetOption('importAllDatasets', $pa_options, false);
     $vb_dry_run = caGetOption('dryRun', $pa_options, false);
     $vn_log_level = BatchProcessor::_logLevelStringToNumber($vs_log_level);
     if (!isURL($ps_source) && is_dir($ps_source)) {
         $va_sources = caGetDirectoryContentsAsList($ps_source, true, false, false, false);
     } else {
         $va_sources = array($ps_source);
     }
     $vn_file_num = 0;
     foreach ($va_sources as $vs_source) {
         $vn_file_num++;
         if (!ca_data_importers::importDataFromSource($vs_source, $ps_importer, array('fileNumber' => $vn_file_num, 'numberOfFiles' => sizeof($va_sources), 'logDirectory' => $o_config->get('batch_metadata_import_log_directory'), 'request' => $po_request, 'format' => $ps_input_format, 'showCLIProgressBar' => false, 'useNcurses' => false, 'progressCallback' => isset($pa_options['progressCallback']) ? $pa_options['progressCallback'] : null, 'reportCallback' => isset($pa_options['reportCallback']) ? $pa_options['reportCallback'] : null, 'logDirectory' => $vs_log_dir, 'logLevel' => $vn_log_level, 'dryRun' => $vb_dry_run, 'importAllDatasets' => $vb_import_all_datasets))) {
             $va_errors['general'][] = array('idno' => "*", 'label' => "*", 'errors' => array(_t("Could not import source %1", $ps_source)), 'status' => 'ERROR');
             return false;
         } else {
             $va_notices['general'][] = array('idno' => "*", 'label' => "*", 'errors' => array(_t("Imported data from source %1", $ps_source)), 'status' => 'SUCCESS');
             //return true;
         }
     }
     $vn_elapsed_time = time() - $vn_start_time;
     if (isset($pa_options['sendMail']) && $pa_options['sendMail']) {
         if ($vs_email = trim($po_request->user->get('email'))) {
             caSendMessageUsingView($po_request, array($vs_email => $po_request->user->get('fname') . ' ' . $po_request->user->get('lname')), __CA_ADMIN_EMAIL__, _t('[%1] Batch metadata import completed', $po_request->config->get('app_display_name')), 'batch_metadata_import_completed.tpl', array('notices' => $va_notices, 'errors' => $va_errors, 'numErrors' => sizeof($va_errors), 'numProcessed' => sizeof($va_notices), 'subjectNameSingular' => _t('row'), 'subjectNamePlural' => _t('rows'), 'startedOn' => caGetLocalizedDate($vn_start_time), 'completedOn' => caGetLocalizedDate(time()), 'elapsedTime' => caFormatInterval($vn_elapsed_time)));
         }
     }
     if (isset($pa_options['sendSMS']) && $pa_options['sendSMS']) {
         SMS::send($po_request->getUserID(), _t("[%1] Metadata import processing for begun at %2 is complete", $po_request->config->get('app_display_name'), caGetLocalizedDate($vn_start_time)));
     }
     return array('errors' => $va_errors, 'notices' => $va_notices, 'processing_time' => caFormatInterval($vn_elapsed_time));
 }
 /**
  * Import SIPs from specified directory into CollectiveAccess Database
  */
 public function commandImportSIPs()
 {
     $o_conf = $this->getToolConfig();
     $t = new Timer();
     // Get locale from config and translate to numeric code
     $t_locale = new ca_locales();
     $pn_locale_id = $t_locale->localeCodeToID($o_conf->get('locale'));
     $o_log = $this->getLogger();
     $o_progress = $this->getProgressBar(0);
     if ($o_progress) {
         $o_progress->start("Starting import");
     }
     $vs_import_directory = $this->getSetting("import_directory");
     if (!is_readable($vs_import_directory)) {
         if ($o_log) {
             $o_log->logError($vs_err_msg = _t("Import directory %1 is not readable", $vs_import_directory));
         }
         if ($o_progress) {
             $o_progress->setError($vs_err_msg);
             $o_progress->finish();
         }
         return false;
     }
     if ($o_log) {
         $o_log->logDebug(_t("Started SIP import"));
     }
     //print "[1] ".$t->getTime(4)."\n";
     // Look for ZIP files or directories
     $va_files = caGetDirectoryContentsAsList($vs_import_directory, false, false, false, true);
     //print "[2] ".$t->getTime(4)."\n";
     $vn_count = 0;
     foreach ($va_files as $vs_file) {
         if (!preg_match("!\\.zip\$!i", $vs_file) && !is_dir($vs_file)) {
             continue;
         }
         $vn_count++;
     }
     $o_progress->setTotal($vn_count);
     //print "[3] ".$t->getTime(4)."\n";
     foreach ($va_files as $vs_file) {
         // Top level zips or directories
         $vb_is_dir = is_dir($vs_file);
         if (!preg_match("!\\.zip\$!i", $vs_file) && !$vb_is_dir) {
             continue;
         }
         //print "[4] ".$t->getTime(4)."\n";
         $o_progress->setMessage(_t('Processing %1', $vs_file));
         // unpack ZIP
         $va_package_files = caGetDirectoryContentsAsList($vb_is_dir ? $vs_file : 'phar://' . $vs_file . '/', false, false, false, true);
         // files in top level of directory or zip
         //foreach($va_package_files as $vs_package_path) {
         //$va_tmp = explode("/", $vs_package_path);
         //$vs_package_dir = array_pop($va_tmp);
         $va_archive_files = caGetDirectoryContentsAsList($vb_is_dir ? $vs_file : 'phar://' . $vs_file, true);
         // Does it look like a SIP?
         $vb_is_sip = false;
         $vs_idno = $vs_idno_padded = $vs_zip_path = $vs_category = null;
         $va_sides = array();
         foreach ($va_archive_files as $vs_archive_file) {
             if ($o_log) {
                 $o_log->logDebug(_t("Testing file %1 for SIP-ness", $vs_archive_file));
             }
             if (preg_match("!category.txt\$!", $vs_archive_file)) {
                 $vb_is_sip = true;
                 $va_tmp = explode("/", $vs_archive_file);
                 array_pop($va_tmp);
                 // pop category.txt
                 $vs_idno = array_pop($va_tmp);
                 $va_tmp_idno = explode("-", $vs_idno);
                 $va_tmp_idno[2] = str_pad($va_tmp_idno[2], 6, "0", STR_PAD_LEFT);
                 $vs_idno_padded = join("-", $va_tmp_idno);
                 $vs_category = strtolower(preg_replace("![^A-Z \\-a-z0-9]!", "", file_get_contents($vs_archive_file)));
                 // Translate categories
                 switch ($vs_category) {
                     case 'mixed':
                         $vs_category = 'unclassified';
                         break;
                 }
                 $vs_zip_path = join("/", $va_tmp);
                 if ($o_log) {
                     $o_log->logInfo(_t("Found SIP %1 with category %2", $vs_archive_dir, $vs_category));
                 }
                 continue;
             }
         }
         if (!$vb_is_sip) {
             if ($o_progress) {
                 $o_progress->setError(_t('File %1 is not a valid SIP', $vs_file));
             }
             if ($o_log) {
                 $o_log->logWarn(_t('File %1 is not a valid SIP', $vs_file));
             }
             continue;
         }
         //print "[5] ".$t->getTime(4)."\n";
         $va_track_audio_by_side = $va_track_xml_by_side = $va_side_audio = $va_side_xml = $va_artifacts = array();
         // Reset total # of SIPS with contents of ZIP
         $o_progress->setTotal((int) $o_progress->getTotal() - 1 + sizeof($va_archive_files));
         foreach ($va_archive_files as $vs_archive_file) {
             $vs_file_in_zip = str_replace($vb_is_dir ? "{$vs_file}" : "phar://{$vs_file}/{$vs_idno}", "", $vs_archive_file);
             $va_tmp = explode("/", $vs_file_in_zip);
             switch ($va_tmp[1]) {
                 case 'sides':
                     if ($va_tmp[4]) {
                         $vs_ext = pathinfo($va_tmp[4], PATHINFO_EXTENSION);
                         switch ($vs_ext) {
                             case 'mp3':
                                 $va_track_audio_by_side[$va_tmp[2]][] = ($vb_is_dir ? "{$vs_file}/sides/" : "phar://{$vs_file}/{$vs_idno}/sides/") . $va_tmp[2] . "/" . $va_tmp[3] . "/" . $va_tmp[4];
                                 break;
                             case 'xml':
                                 $va_track_xml_by_side[$va_tmp[2]][] = ($vb_is_dir ? "{$vs_file}/sides/" : "phar://{$vs_file}/{$vs_idno}/sides/") . $va_tmp[2] . "/" . $va_tmp[3] . "/" . $va_tmp[4];
                                 break;
                         }
                     } else {
                         if ($va_tmp[2]) {
                             $vs_ext = pathinfo($va_tmp[3], PATHINFO_EXTENSION);
                             switch ($vs_ext) {
                                 case 'mp3':
                                     $va_side_audio[$va_tmp[2]] = $va_tmp[3];
                                     break;
                                 case 'xml':
                                     if (preg_match('!meta!', $va_tmp[3])) {
                                         $va_side_xml[$va_tmp[2]] = ($vb_is_dir ? "{$vs_file}/sides/" : "phar://{$vs_file}/{$vs_idno}/sides/") . $va_tmp[2] . "/" . $va_tmp[3];
                                     }
                                     break;
                             }
                         }
                     }
                     break;
                 case 'artifacts':
                     if (sizeof($va_tmp) == 3) {
                         $va_artifacts[] = ($vb_is_dir ? "{$vs_file}/artifacts/" : "phar://{$vs_file}/{$vs_idno}/artifacts/") . $va_tmp[2];
                     }
                     break;
             }
         }
         //print "[6] ".$t->getTime(4)."\n";
         //print_R($va_side_xml); die;
         // Process
         // Create parent record
         $vn_image_count = 0;
         $o_progress->next(_t('Processing %1', $vs_archive_file));
         $o_progress->setMessage(_t("Creating reel for %1", $vs_idno));
         $va_ids = ca_objects::find(array('idno' => $vs_idno, 'deleted' => 0, 'type_id' => 'reel'), array('returnAs' => 'ids'));
         if (!is_array($va_ids) || !sizeof($va_ids)) {
             $t_object = new ca_objects();
             $t_object->setMode(ACCESS_WRITE);
             $t_object->set(array('status' => 5, 'type_id' => 'reel', 'idno' => $vs_idno));
             $vn_object_id = $t_object->insert();
             if ($t_object->numErrors()) {
                 if ($o_log) {
                     $o_log->logError(_t("Could not add reel record %1: %2", $vs_idno, join("; ", $t_object->getErrors())));
                 }
             }
             $t_object->addLabel(array('name' => $vs_idno_padded), $pn_locale_id, null, true);
             if ($t_object->numErrors()) {
                 if ($o_log) {
                     $o_log->logError(_t("Could not add label to reel record %1: %2", $vs_idno, join("; ", $t_object->getErrors())));
                 }
             }
             if ($t_object->numErrors()) {
                 if ($o_log) {
                     $o_log->logError(_t("Could not add artifct media %1 to reel %2: %3", pathinfo($vs_artifact, PATHINFO_BASENAME), $vs_idno, join("; ", $t_object->getErrors())));
                 }
             }
         } else {
             if ($o_log) {
                 $o_log->logDebug(_t("Found existing reel record %1 for %2", $va_ids[0], $vs_idno));
             }
             $t_object = new ca_objects($vn_object_id = $va_ids[0]);
             $t_object->setMode(ACCESS_WRITE);
             $t_object->set('status', 5);
             $t_object->update();
             if (($vn_image_count = $t_object->numberOfRepresentationsOfClass("image")) > 0) {
                 // skip reels that have images already
                 //if ($o_log) { $o_log->logDebug(_t("Skipped existing reel record %1 because it already has %2 images", $vs_idno, $vn_image_count)); }
                 //if ($o_progress) { $o_progress->setError(_t("Skipped existing reel record %1 because it already has %2 images", $vs_idno, $vn_image_count)); }
                 //continue;
             }
             $t_object->setMode(ACCESS_WRITE);
         }
         //print "[7] ".$t->getTime(4)."\n";
         if ($vn_image_count > 0) {
             $t_object->removeAllRepresentations();
             if ($t_object->numErrors()) {
                 if ($o_log) {
                     $o_log->logError(_t("Could not add remove existing media from reel %1: %2", $vs_idno, join("; ", $t_object->getErrors())));
                 }
             }
         }
         $o_progress->setMessage(_t("Linking artifact images for %1", $vs_idno));
         foreach ($va_artifacts as $vs_artifact) {
             $o_progress->next(_t('Processing artifact image %1', $vs_artifact));
             copy($vs_artifact, $vs_tmp_filepath = "/tmp/pbc" . md5(time()));
             $t_object->addRepresentation($vs_tmp_filepath, 'front', $pn_locale_id, 0, 1, 1);
             $o_progress->setMessage(_t("Added artifact image %1 for %2", $vs_artifact, $vs_idno));
             if ($t_object->numErrors()) {
                 if ($o_log) {
                     $o_log->logError(_t("Could not add artifact media %1 to reel %2: %3", pathinfo($vs_artifact, PATHINFO_BASENAME), $vs_idno, join("; ", $t_object->getErrors())));
                 }
             }
             // remove tmp file
             @unlink($vs_tmp_filepath);
         }
         //
         // Add XML
         //
         $o_progress->setMessage(_t("Adding XML for %1", $vs_track_idno));
         $t_object->removeAttributes('sip_metadata');
         foreach ($va_side_xml as $vs_side => $vs_xml_path) {
             copy($vs_xml_path, $vs_xml_tmppath = "/tmp/" . pathinfo($vs_xml_path, PATHINFO_BASENAME));
             $o_progress->next(_t('Processing XML %1', $vs_xml_tmppath));
             $t_object->addAttribute(array('sip_metadata' => $vs_xml_tmppath, 'locale_id' => $pn_locale_id), 'sip_metadata');
             $t_object->update();
             if ($t_object->numErrors()) {
                 if ($o_log) {
                     $o_log->logError(_t("Could not import XML file %1 into reel %2: %3", pathinfo($va_track_xml_by_side[$vs_side][$vn_i], PATHINFO_BASENAME), $vs_track_idno, join("; ", $t_object->getErrors())));
                 }
             }
         }
         //print "[8] ".$t->getTime(4)."\n";
         // Create tracks
         $o_progress->setMessage(_t("Creating tracks for %1", $vs_idno));
         foreach ($va_track_audio_by_side as $vs_side => $va_tracks) {
             foreach ($va_tracks as $vn_i => $vs_audio) {
                 $o_progress->next(_t('Processing track %1', $vs_audio));
                 $vs_ext = pathinfo($vs_audio, PATHINFO_EXTENSION);
                 copy($vs_audio, $vs_tmp_filepath = "/tmp/pbc" . md5(time()) . ".{$vs_ext}");
                 $vs_track_idno = pathinfo($vs_audio, PATHINFO_FILENAME);
                 // Does track already exist?
                 $va_track_ids = ca_objects::find(array('idno' => $vs_track_idno, 'deleted' => 0), array('returnAs' => 'ids'));
                 if (!is_array($va_track_ids) || !sizeof($va_track_ids)) {
                     $o_progress->setMessage(_t("Creating %2 track for %1", $vs_track_idno, $vs_category));
                     // Create track record
                     $t_track = new ca_objects();
                     $t_track->setMode(ACCESS_WRITE);
                     $va_tmp = explode("/", $vs_audio);
                     $vs_category = strtolower(str_replace(' ', '_', $vs_category));
                     $t_track->set(array('type_id' => $vs_category, 'idno' => $vs_track_idno, 'parent_id' => $vn_object_id));
                     $vn_track_id = $t_track->insert();
                     if ($t_track->numErrors()) {
                         if ($o_log) {
                             $o_log->logError(_t("Could not add track %1: %2", $vs_track_idno, join("; ", $t_track->getErrors())));
                         }
                     }
                     $t_track->addLabel(array('name' => "{$vs_track_idno}"), $pn_locale_id, null, true);
                     if ($t_track->numErrors()) {
                         if ($o_log) {
                             $o_log->logError(_t("Could not add label to track %1: %2", $vs_track_idno, join("; ", $t_track->getErrors())));
                         }
                     }
                 } else {
                     if ($o_log) {
                         $o_log->logDebug(_t("Found existing track record %1 for %2", $va_track_ids[0], $vs_track_idno));
                     }
                     $t_track = new ca_objects($va_track_ids[0]);
                     if (($vn_audio_count = $t_track->numberOfRepresentationsOfClass("audio")) > 0) {
                         // skip tracks that have audio already
                         //if ($o_log) { $o_log->logDebug(_t("Skip existing track record %1 because it already has %2 audio files", $vs_track_idno, $vn_audio_count)); }
                         //continue;
                         $t_track->removeAllRepresentations();
                     }
                 }
                 //
                 // Add track audio
                 //
                 $o_progress->setMessage(_t("Adding track audio for %1", $vs_track_idno));
                 $t_track->addRepresentation($vs_tmp_filepath, 'front', $pn_locale_id, 0, 1, 1);
                 if ($t_track->numErrors()) {
                     if ($o_log) {
                         $o_log->logError($vs_err_msg = _t("Could not import audio file %1 into track %2: %3", pathinfo($vs_audio, PATHINFO_BASENAME), $vs_track_idno, join("; ", $t_track->getErrors())));
                     }
                     if ($o_progress) {
                         $o_progress->setError($vs_err_msg);
                     }
                 }
                 // Remove tmp files
                 @unlink($vs_tmp_filepath);
                 @unlink($vs_xml_tmppath);
             }
         }
         //print "[9] ".$t->getTime(4)."\n";
         //}
         if ((bool) $this->getSetting('delete_after_import')) {
             $o_progress->setMessage(_t("Deleting SIP %1", $vs_file));
             if ($vb_is_dir) {
                 caRemoveDirectory($vs_file);
             } else {
                 @unlink($vs_file);
             }
         }
     }
     //print "[10] ".$t->getTime(4)."\n";
     $o_progress->finish("Completed processing");
     if ($o_log) {
         $o_log->logDebug(_t("Ended SIP import"));
     }
     //print "DONE\n\n";
     return true;
 }
Example #13
0
 /**
  * @param array $pa_options
  *		progressCallback =
  *		reportCallback = 
  *		sendMail = 
  */
 public static function importMediaFromDirectory($po_request, $pa_options = null)
 {
     global $g_ui_locale_id;
     $t_object = new ca_objects();
     $o_eventlog = new Eventlog();
     $t_set = new ca_sets();
     $va_notices = $va_errors = array();
     $vb_we_set_transaction = false;
     $o_trans = isset($pa_options['transaction']) && $pa_options['transaction'] ? $pa_options['transaction'] : null;
     if (!$o_trans) {
         $vb_we_set_transaction = true;
         $o_trans = new Transaction();
     }
     $o_log = new Batchlog(array('user_id' => $po_request->getUserID(), 'batch_type' => 'MI', 'table_num' => (int) $t_object->tableNum(), 'notes' => '', 'transaction' => $o_trans));
     if (!is_dir($pa_options['importFromDirectory'])) {
         $o_eventlog->log(array("CODE" => 'ERR', "SOURCE" => "mediaImport", "MESSAGE" => "Specified import directory is invalid"));
         return null;
     }
     $vs_batch_media_import_root_directory = $po_request->config->get('batch_media_import_root_directory');
     if (!preg_match("!^{$vs_batch_media_import_root_directory}!", $pa_options['importFromDirectory'])) {
         $o_eventlog->log(array("CODE" => 'ERR', "SOURCE" => "mediaImport", "MESSAGE" => "Specified import directory is invalid"));
         return null;
     }
     if (preg_match("!/\\.\\.!", $vs_directory) || preg_match("!\\.\\./!", $pa_options['importFromDirectory'])) {
         $o_eventlog->log(array("CODE" => 'ERR', "SOURCE" => "mediaImport", "MESSAGE" => "Specified import directory is invalid"));
         return null;
     }
     $vb_include_subdirectories = (bool) $pa_options['includeSubDirectories'];
     $vb_delete_media_on_import = (bool) $pa_options['deleteMediaOnImport'];
     $vs_import_mode = $pa_options['importMode'];
     $vs_match_mode = $pa_options['matchMode'];
     $vn_object_type_id = $pa_options['ca_objects_type_id'];
     $vn_rep_type_id = $pa_options['ca_object_representations_type_id'];
     $vn_object_access = $pa_options['ca_objects_access'];
     $vn_object_representation_access = $pa_options['ca_object_representations_access'];
     $vn_object_status = $pa_options['ca_objects_status'];
     $vn_object_representation_status = $pa_options['ca_object_representations_status'];
     $vs_idno_mode = $pa_options['idnoMode'];
     $vs_idno = $pa_options['idno'];
     $vs_set_mode = $pa_options['setMode'];
     $vs_set_create_name = $pa_options['setCreateName'];
     $vn_set_id = $pa_options['set_id'];
     $vn_locale_id = $pa_options['locale_id'];
     $vs_skip_file_list = $pa_options['skipFileList'];
     $va_relationship_type_id_for = array();
     if (is_array($va_create_relationship_for = $pa_options['create_relationship_for'])) {
         foreach ($va_create_relationship_for as $vs_rel_table) {
             $va_relationship_type_id_for[$vs_rel_table] = $pa_options['relationship_type_id_for_' . $vs_rel_table];
         }
     }
     if (!$vn_locale_id) {
         $vn_locale_id = $g_ui_locale_id;
     }
     $va_files_to_process = caGetDirectoryContentsAsList($pa_options['importFromDirectory'], $vb_include_subdirectories);
     if ($vs_set_mode == 'add') {
         $t_set->load($vn_set_id);
     } else {
         if ($vs_set_mode == 'create' && $vs_set_create_name) {
             $va_set_ids = $t_set->getSets(array('user_id' => $po_request->getUserID(), 'table' => 'ca_objects', 'access' => __CA_SET_EDIT_ACCESS__, 'setIDsOnly' => true, 'name' => $vs_set_create_name));
             $vn_set_id = null;
             if (is_array($va_set_ids) && sizeof($va_set_ids) > 0) {
                 $vn_possible_set_id = array_shift($va_set_ids);
                 if ($t_set->load($vn_possible_set_id)) {
                     $vn_set_id = $t_set->getPrimaryKey();
                 }
             } else {
                 $vs_set_code = mb_substr(preg_replace("![^A-Za-z0-9_\\-]+!", "_", $vs_set_create_name), 0, 100);
                 if ($t_set->load(array('set_code' => $vs_set_code))) {
                     $vn_set_id = $t_set->getPrimaryKey();
                 }
             }
             if (!$t_set->getPrimaryKey()) {
                 $t_set->setMode(ACCESS_WRITE);
                 $t_set->set('user_id', $po_request->getUserID());
                 $t_set->set('type_id', $po_request->config->get('ca_sets_default_type'));
                 $t_set->set('table_num', $t_object->tableNum());
                 $t_set->set('set_code', $vs_set_code);
                 $t_set->insert();
                 if ($t_set->numErrors()) {
                     $va_notices['create_set'] = array('idno' => '', 'label' => _t('Create set %1', $vs_set_create_name), 'message' => _t('Failed to create set %1: %2', $vs_set_create_name, join("; ", $t_set->getErrors())), 'status' => 'SET ERROR');
                 } else {
                     $t_set->addLabel(array('name' => $vs_set_create_name), $vn_locale_id, null, true);
                     if ($t_set->numErrors()) {
                         $va_notices['add_set_label'] = array('idno' => '', 'label' => _t('Add label to set %1', $vs_set_create_name), 'message' => _t('Failed to add label to set: %1', join("; ", $t_set->getErrors())), 'status' => 'SET ERROR');
                     }
                     $vn_set_id = $t_set->getPrimaryKey();
                 }
             }
         } else {
             $vn_set_id = null;
             // no set
         }
     }
     if ($t_set->getPrimaryKey() && !$t_set->haveAccessToSet($po_request->getUserID(), __CA_SET_EDIT_ACCESS__)) {
         $va_notices['set_access'] = array('idno' => '', 'label' => _t('You do not have access to set %1', $vs_set_create_name), 'message' => _t('Cannot add to set %1 because you do not have edit access', $vs_set_create_name), 'status' => 'SET ERROR');
         $vn_set_id = null;
         $t_set = new ca_sets();
     }
     $vn_num_items = sizeof($va_files_to_process);
     // Get list of regex packages that user can use to extract object idno's from filenames
     $va_regex_list = $po_request->config->getAssoc('mediaFilenameToObjectIdnoRegexes');
     if (!is_array($va_regex_list)) {
         $va_regex_list = array();
     }
     // Get list of files (or file name patterns) to skip
     $va_skip_list = preg_split("![\r\n]+!", $vs_skip_file_list);
     foreach ($va_skip_list as $vn_i => $vs_skip) {
         if (!strlen($va_skip_list[$vn_i] = trim($vs_skip))) {
             unset($va_skip_list[$vn_i]);
         }
     }
     $vn_c = 0;
     $vn_start_time = time();
     $va_report = array();
     foreach ($va_files_to_process as $vs_file) {
         $va_tmp = explode("/", $vs_file);
         $f = array_pop($va_tmp);
         $d = array_pop($va_tmp);
         array_push($va_tmp, $d);
         $vs_directory = join("/", $va_tmp);
         // Skip file names using $vs_skip_file_list
         if (BatchProcessor::_skipFile($f, $va_skip_list)) {
             continue;
         }
         $vs_relative_directory = preg_replace("!{$vs_batch_media_import_root_directory}[/]*!", "", $vs_directory);
         // does representation already exist?
         if (ca_object_representations::mediaExists($vs_file)) {
             $va_notices[$vs_relative_directory . '/' . $f] = array('idno' => '', 'label' => $f, 'message' => _t('Skipped %1 from %2 because it already exists', $f, $vs_relative_directory), 'status' => 'SKIPPED');
             continue;
         }
         $t_object = new ca_objects();
         $t_object->setTransaction($o_trans);
         $vs_modified_filename = $f;
         $va_extracted_idnos_from_filename = array();
         if (in_array($vs_import_mode, array('TRY_TO_MATCH', 'ALWAYS_MATCH')) || is_array($va_create_relationship_for) && sizeof($va_create_relationship_for)) {
             foreach ($va_regex_list as $vs_regex_name => $va_regex_info) {
                 foreach ($va_regex_info['regexes'] as $vs_regex) {
                     $va_names_to_match = array();
                     switch ($vs_match_mode) {
                         case 'DIRECTORY_NAME':
                             $va_names_to_match = array($d);
                             break;
                         case 'FILE_AND_DIRECTORY_NAMES':
                             $va_names_to_match = array($f, $d);
                             break;
                         default:
                         case 'FILE_NAME':
                             $va_names_to_match = array($f);
                             break;
                     }
                     foreach ($va_names_to_match as $vs_match_name) {
                         if (preg_match('!' . $vs_regex . '!', $vs_match_name, $va_matches)) {
                             if (!$vs_idno || strlen($va_matches[1]) < strlen($vs_idno)) {
                                 $vs_idno = $va_matches[1];
                             }
                             if (!$vs_modified_filename || strlen($vs_modified_filename) > strlen($va_matches[1])) {
                                 $vs_modified_filename = $va_matches[1];
                             }
                             $va_extracted_idnos_from_filename[] = $va_matches[1];
                             if (in_array($vs_import_mode, array('TRY_TO_MATCH', 'ALWAYS_MATCH'))) {
                                 if ($t_object->load(array('idno' => $va_matches[1], 'deleted' => 0))) {
                                     $va_notices[$vs_relative_directory . '/' . $vs_match_name . '_match'] = array('idno' => $t_object->get($t_object->getProperty('ID_NUMBERING_ID_FIELD')), 'label' => $t_object->getLabelForDisplay(), 'message' => _t('Matched media %1 from %2 to object using %2', $f, $vs_relative_directory, $vs_regex_name), 'status' => 'MATCHED');
                                     break 3;
                                 }
                             }
                         }
                     }
                 }
             }
         }
         if (!$t_object->getPrimaryKey()) {
             // Use filename as idno if all else fails
             if ($t_object->load(array('idno' => $f, 'deleted' => 0))) {
                 $va_notices[$vs_relative_directory . '/' . $f . '_match'] = array('idno' => $t_object->get($t_object->getProperty('ID_NUMBERING_ID_FIELD')), 'label' => $t_object->getLabelForDisplay(), 'message' => _t('Matched media %1 from %2 to object using filename', $f, $vs_relative_directory), 'status' => 'MATCHED');
             }
         }
         $t_new_rep = null;
         if ($t_object->getPrimaryKey()) {
             // found existing object
             $t_object->setMode(ACCESS_WRITE);
             $t_new_rep = $t_object->addRepresentation($vs_directory . '/' . $f, $vn_rep_type_id, $vn_locale_id, $vn_object_representation_status, $vn_object_representation_access, false, array(), array('original_filename' => $f, 'returnRepresentation' => true));
             if ($t_object->numErrors()) {
                 $o_eventlog->log(array("CODE" => 'ERR', "SOURCE" => "mediaImport", "MESSAGE" => "Error importing {$f} from {$vs_directory}: " . join('; ', $t_object->getErrors())));
                 $va_errors[$vs_relative_directory . '/' . $f] = array('idno' => $t_object->get($t_object->getProperty('ID_NUMBERING_ID_FIELD')), 'label' => $t_object->getLabelForDisplay(), 'errors' => $t_object->errors(), 'message' => _t("Error importing %1 from %2: %3", $f, $vs_relative_directory, join('; ', $t_object->getErrors())), 'status' => 'ERROR');
                 $o_trans->rollback();
                 continue;
             } else {
                 if ($vb_delete_media_on_import) {
                     @unlink($vs_directory . '/' . $f);
                 }
             }
         } else {
             // should we create new object?
             if (in_array($vs_import_mode, array('TRY_TO_MATCH', 'DONT_MATCH'))) {
                 $t_object->setMode(ACCESS_WRITE);
                 $t_object->set('type_id', $vn_object_type_id);
                 $t_object->set('locale_id', $vn_locale_id);
                 $t_object->set('status', $vn_object_status);
                 $t_object->set('access', $vn_object_access);
                 switch ($vs_idno_mode) {
                     case 'filename':
                         // use the filename as identifier
                         $t_object->set('idno', $f);
                         break;
                     case 'directory_and_filename':
                         // use the directory + filename as identifier
                         $t_object->set('idno', $d . '/' . $f);
                         break;
                     default:
                         // Calculate identifier using numbering plugin
                         $o_numbering_plugin = $t_object->getIDNoPlugInInstance();
                         if (!($vs_sep = $o_numbering_plugin->getSeparator())) {
                             $vs_sep = '';
                         }
                         if (!is_array($va_idno_values = $o_numbering_plugin->htmlFormValuesAsArray('idno', $vs_object_idno, false, false, true))) {
                             $va_idno_values = array();
                         }
                         $t_object->set('idno', join($vs_sep, $va_idno_values));
                         // true=always set serial values, even if they already have a value; this let's us use the original pattern while replacing the serial value every time through
                         break;
                 }
                 $t_object->insert();
                 if ($t_object->numErrors()) {
                     $o_eventlog->log(array("CODE" => 'ERR', "SOURCE" => "mediaImport", "MESSAGE" => "Error creating new object while importing {$f} from {$vs_relative_directory}: " . join('; ', $t_object->getErrors())));
                     $va_errors[$vs_relative_directory . '/' . $f] = array('idno' => $t_object->get($t_object->getProperty('ID_NUMBERING_ID_FIELD')), 'label' => $t_object->getLabelForDisplay(), 'errors' => $t_object->errors(), 'message' => _t("Error creating new object while importing %1 from %2: %3", $f, $vs_relative_directory, join('; ', $t_object->getErrors())), 'status' => 'ERROR');
                     $o_trans->rollback();
                     continue;
                 }
                 $t_object->addLabel(array('name' => $f), $vn_locale_id, null, true);
                 if ($t_object->numErrors()) {
                     $o_eventlog->log(array("CODE" => 'ERR', "SOURCE" => "mediaImport", "MESSAGE" => "Error creating object label while importing {$f} from {$vs_relative_directory}: " . join('; ', $t_object->getErrors())));
                     $va_errors[$vs_relative_directory . '/' . $f] = array('idno' => $t_object->get($t_object->getProperty('ID_NUMBERING_ID_FIELD')), 'label' => $t_object->getLabelForDisplay(), 'errors' => $t_object->errors(), 'message' => _t("Error creating object label while importing %1 from %2: %3", $f, $vs_relative_directory, join('; ', $t_object->getErrors())), 'status' => 'ERROR');
                     $o_trans->rollback();
                     continue;
                 }
                 $t_new_rep = $t_object->addRepresentation($vs_directory . '/' . $f, $vn_rep_type_id, $vn_locale_id, $vn_object_representation_status, $vn_object_representation_access, true, array(), array('original_filename' => $f, 'returnRepresentation' => true));
                 if ($t_object->numErrors()) {
                     $o_eventlog->log(array("CODE" => 'ERR', "SOURCE" => "mediaImport", "MESSAGE" => "Error importing {$f} from {$vs_relative_directory}: " . join('; ', $t_object->getErrors())));
                     $va_errors[$vs_relative_directory . '/' . $f] = array('idno' => $t_object->get($t_object->getProperty('ID_NUMBERING_ID_FIELD')), 'label' => $t_object->getLabelForDisplay(), 'errors' => $t_object->errors(), 'message' => _t("Error importing %1 from %2: %3", $f, $vs_relative_directory, join('; ', $t_object->getErrors())), 'status' => 'ERROR');
                     $o_trans->rollback();
                     continue;
                 } else {
                     if ($vb_delete_media_on_import) {
                         @unlink($vs_directory . '/' . $f);
                     }
                 }
             }
         }
         if ($t_object->getPrimaryKey()) {
             $va_notices[$t_object->getPrimaryKey()] = array('idno' => $t_object->get($t_object->getProperty('ID_NUMBERING_ID_FIELD')), 'label' => $t_object->getLabelForDisplay(), 'message' => _t('Imported %1 as %2', $f, $t_object->get($t_object->getProperty('ID_NUMBERING_ID_FIELD'))), 'status' => 'SUCCESS');
             if ($vn_set_id) {
                 $t_set->addItem($t_object->getPrimaryKey(), null, $po_request->getUserID());
             }
             $o_log->addItem($t_object->getPrimaryKey(), $t_object->getErrors());
             // Create relationships?
             if (is_array($va_create_relationship_for) && sizeof($va_create_relationship_for) && is_array($va_extracted_idnos_from_filename) && sizeof($va_extracted_idnos_from_filename)) {
                 foreach ($va_extracted_idnos_from_filename as $vs_idno) {
                     foreach ($va_create_relationship_for as $vs_rel_table) {
                         if (!isset($va_relationship_type_id_for[$vs_rel_table]) || !$va_relationship_type_id_for[$vs_rel_table]) {
                             continue;
                         }
                         $t_rel = $t_object->getAppDatamodel()->getInstanceByTableName($vs_rel_table);
                         if ($t_rel->load(array($t_rel->getProperty('ID_NUMBERING_ID_FIELD') => $vs_idno))) {
                             $t_object->addRelationship($vs_rel_table, $t_rel->getPrimaryKey(), $va_relationship_type_id_for[$vs_rel_table]);
                             if (!$t_object->numErrors()) {
                                 $va_notices[$t_object->getPrimaryKey() . '_rel'] = array('idno' => $t_object->get($t_object->getProperty('ID_NUMBERING_ID_FIELD')), 'label' => $vs_label = $t_object->getLabelForDisplay(), 'message' => _t('Added relationship between <em>%1</em> and %2 <em>%3</em>', $vs_label, $t_rel->getProperty('NAME_SINGULAR'), $t_rel->getLabelForDisplay()), 'status' => 'RELATED');
                             } else {
                                 $va_notices[$t_object->getPrimaryKey()] = array('idno' => $t_object->get($t_object->getProperty('ID_NUMBERING_ID_FIELD')), 'label' => $vs_label = $t_object->getLabelForDisplay(), 'message' => _t('Could not add relationship between <em>%1</em> and %2 <em>%3</em>: %4', $vs_label, $t_rel->getProperty('NAME_SINGULAR'), $t_rel->getLabelForDisplay(), join("; ", $t_object->getErrors())), 'status' => 'ERROR');
                             }
                         }
                     }
                 }
             }
         } else {
             $va_notices[$vs_relative_directory . '/' . $f] = array('idno' => '', 'label' => $f, 'message' => $vs_import_mode == 'ALWAYS_MATCH' ? _t('Skipped %1 from %2 because it could not be matched', $f, $vs_relative_directory) : _t('Skipped %1 from %2', $f, $vs_relative_directory), 'status' => 'SKIPPED');
         }
         if (isset($pa_options['progressCallback']) && ($ps_callback = $pa_options['progressCallback'])) {
             $ps_callback($po_request, $vn_c, $vn_num_items, _t("[%3/%4] Processing %1 (%3)", caTruncateStringWithEllipsis($vs_relative_directory, 20) . '/' . caTruncateStringWithEllipsis($f, 30), $t_object->get($t_object->getProperty('ID_NUMBERING_ID_FIELD')), $vn_c, $vn_num_items), $t_new_rep, time() - $vn_start_time, memory_get_usage(true), sizeof($va_notices), sizeof($va_errors));
         }
         $vn_c++;
     }
     if (isset($pa_options['progressCallback']) && ($ps_callback = $pa_options['progressCallback'])) {
         $ps_callback($po_request, $vn_num_items, $vn_num_items, _t("Processing completed"), null, time() - $vn_start_time, memory_get_usage(true), sizeof($va_notices), sizeof($va_errors));
     }
     $vn_elapsed_time = time() - $vn_start_time;
     if (isset($pa_options['reportCallback']) && ($ps_callback = $pa_options['reportCallback'])) {
         $va_general = array('elapsedTime' => $vn_elapsed_time, 'numErrors' => sizeof($va_errors), 'numProcessed' => sizeof($va_notices), 'batchSize' => $vn_num_items, 'table' => 'ca_objects', 'set_id' => $t_set->getPrimaryKey(), 'setName' => $t_set->getLabelForDisplay());
         $ps_callback($po_request, $va_general, $va_notices, $va_errors);
     }
     $o_log->close();
     if ($vb_we_set_transaction) {
         if (sizeof($va_errors) > 0) {
             $o_trans->rollback();
         } else {
             $o_trans->commit();
         }
     }
     $vs_set_name = $t_set->getLabelForDisplay();
     $vs_started_on = caGetLocalizedDate($vn_start_time);
     if (isset($pa_options['sendMail']) && $pa_options['sendMail']) {
         if ($vs_email = trim($po_request->user->get('email'))) {
             caSendMessageUsingView($po_request, array($vs_email => $po_request->user->get('fname') . ' ' . $po_request->user->get('lname')), __CA_ADMIN_EMAIL__, _t('[%1] Batch media import completed', $po_request->config->get('app_display_name')), 'batch_media_import_completed.tpl', array('notices' => $va_notices, 'errors' => $va_errors, 'directory' => $vs_relative_directory, 'numErrors' => sizeof($va_errors), 'numProcessed' => sizeof($va_notices), 'subjectNameSingular' => _t('file'), 'subjectNamePlural' => _t('files'), 'startedOn' => $vs_started_on, 'completedOn' => caGetLocalizedDate(time()), 'setName' => $vn_set_id ? $vs_set_name : null, 'elapsedTime' => caFormatInterval($vn_elapsed_time)));
         }
     }
     if (isset($pa_options['sendSMS']) && $pa_options['sendSMS']) {
         SMS::send($po_request->getUserID(), _t("[%1] Media import processing for directory %2 with %3 %4 begun at %5 is complete", $po_request->config->get('app_display_name'), $vs_relative_directory, $vn_num_items, $vn_num_items == 1 ? _t('file') : _t('files'), $vs_started_on));
     }
     return array('errors' => $va_errors, 'notices' => $va_notices, 'processing_time' => caFormatInterval($vn_elapsed_time));
 }
 /**
  * Handle ajax media uploads from editor
  */
 public function UploadFiles($pa_options = null)
 {
     if (!$this->request->isLoggedIn() || (int) $this->request->user->get('userclass') !== 0) {
         $this->response->setRedirect($this->request->config->get('error_display_url') . '/n/2320?r=' . urlencode($this->request->getFullUrlPath()));
         return;
     }
     // use configured directory to dump media with fallback to standard tmp directory
     if (!is_writeable($vs_tmp_directory = $this->request->config->get('ajax_media_upload_tmp_directory'))) {
         $vs_tmp_directory = caGetTempDirPath();
     }
     $vn_user_id = $this->request->getUserID();
     $vs_user_dir = $vs_tmp_directory . "/userMedia{$vn_user_id}";
     if (!file_exists($vs_user_dir)) {
         mkdir($vs_user_dir);
     }
     if (!($vn_timeout = (int) $this->request->config->get('ajax_media_upload_tmp_directory_timeout'))) {
         $vn_timeout = 24 * 60 * 60;
     }
     // Cleanup any old files here
     $va_files_to_delete = caGetDirectoryContentsAsList($vs_user_dir, true, false, false, true, array('modifiedSince' => time() - $vn_timeout));
     foreach ($va_files_to_delete as $vs_file_to_delete) {
         @unlink($vs_file_to_delete);
     }
     $va_stored_files = array();
     foreach ($_FILES as $vn_i => $va_file) {
         $vs_dest_filename = pathinfo($va_file['tmp_name'], PATHINFO_FILENAME);
         copy($va_file['tmp_name'], $vs_dest_path = $vs_tmp_directory . "/userMedia{$vn_user_id}/{$vs_dest_filename}");
         // write file metadata
         file_put_contents("{$vs_dest_path}_metadata", json_encode(array('original_filename' => $va_file['name'], 'size' => filesize($vs_dest_path))));
         $va_stored_files[$vn_i] = "userMedia{$vn_user_id}/{$vs_dest_filename}";
         // only return the user directory and file name, not the entire path
     }
     print json_encode($va_stored_files);
 }
 /**
  * Cleans up temporary export files older than an hour
  * By then everybody should have gotten everything they need from the export dest screen
  */
 private function cleanOldExportFilesFromTmpDir()
 {
     $va_tmp_dir_contents = caGetDirectoryContentsAsList(__CA_APP_DIR__ . DIRECTORY_SEPARATOR . 'tmp', false);
     foreach ($va_tmp_dir_contents as $vs_file) {
         if (preg_match("/^dataExport/", basename($vs_file))) {
             if (time() - filemtime($vs_file) > 60 * 60) {
                 @unlink($vs_file);
             }
         }
     }
 }
 /**
  * Check if all DB tables have a model file -> DISABLED FOR NOW
  */
 public function potentialtestModelFilesExistDB()
 {
     $va_files = caGetDirectoryContentsAsList(__CA_MODELS_DIR__);
     foreach ($va_files as &$vs_f) {
         $vs_f = str_replace(__CA_MODELS_DIR__, "", $vs_f);
         $vs_f = str_replace("/", "", $vs_f);
         $vs_f = str_replace(".php", "", $vs_f);
     }
     $vo_db = new Db();
     $qr_tables = $vo_db->query("show tables");
     while ($qr_tables->nextRow()) {
         $vs_table = $qr_tables->get("Tables_in_" . __CA_DB_DATABASE__);
         if (!in_array($vs_table, $va_files)) {
             print "DB TABLE {$vs_table} DOESN'T HAVE A MODEL FILE!\n";
         }
         $this->assertTrue(in_array($vs_table, $va_files));
     }
 }