/** * */ public function sync() { $this->opa_processed_records = array(); $this->opa_processed_self_relations = array(); $o_config = Configuration::load(__CA_CONF_DIR__ . "/synchronization.conf"); $o_dm = Datamodel::load(); $va_sources = $o_config->getAssoc('sources'); foreach ($va_sources as $vs_code => $va_source) { $vs_base_url = $va_source['baseUrl']; $vs_search_expression = $va_source['searchExpression']; $vs_username = $va_source['username']; $vs_password = $va_source['password']; $vs_table = $va_source['table']; if (!$vs_base_url) { print "ERROR: You must pass a valid CollectiveAccess url\n"; exit(-1); } print "[Notice] Processing {$vs_base_url}/{$vs_code}\n"; if (!($t_instance = $o_dm->getInstanceByTableName($vs_table, false))) { die("Invalid table '{$vs_table}'\n"); } // // Set up HTTP client for REST calls // $o_client = new RestClient($vs_base_url . "/service.php/search/Search/rest"); // // Authenticate // $o_res = $o_client->auth($vs_username, $vs_password)->get(); if (!$o_res->isSuccess()) { die("Could not authenticate to service for authentication\n"); } // // Get userID // $o_res = $o_client->getUserID()->get(); if (!$o_res->isSuccess()) { die("Could not fetch user_id\n"); } $vn_user_id = (int) $o_res->getUserID->response; // // Get date/time on server // $o_res = $o_client->getServerTime()->get(); if (!$o_res->isSuccess()) { die("Could not fetch server time\n"); } $vn_server_timestamp = (int) $o_res->getServerTime->response; // Get last event $va_last_event = ca_data_import_events::getLastEventForSourceAndType($vs_base_url, 'SYNC'); $vs_last_event_timestamp = null; if (is_array($va_last_event)) { if (preg_match('!\\[([^\\]]+)!', $va_last_event['description'], $va_matches)) { $vs_last_event_timestamp = $va_matches[1]; $vs_search_expression = "({$vs_search_expression}) AND (modified:\"after {$vs_last_event_timestamp}\")"; } } else { $vs_search_expression = "({$vs_search_expression}) AND (modified:\"after June 15 2012\")"; } //$vs_search_expression = "modified:\"after 2/24/2013\""; //$vs_search_expression = "ca_objects:idno:10180"; $vs_search_expression = "ca_objects.type_id:48"; print "\t[Notice] Search is for [{$vs_search_expression}]\n"; try { $o_res = $o_client->queryRest($vs_table, $vs_search_expression, array("ca_objects.status" => array("convertCodesToDisplayText" => 1)))->get(); } catch (exception $e) { print "\t[Error] Search failed: " . $e->getMessage() . "\n"; continue; } // TODO: check for errors here //parse results $vs_pk = $t_instance->primaryKey(); $va_items = array(); $o_xml = $o_res->CaSearchResult; foreach ($o_xml->children() as $vn_i => $o_item) { $o_attributes = $o_item->attributes(); $vn_id = (int) $o_attributes->{$vs_pk}; $vs_idno = (string) $o_item->idno; $vs_label = (string) $o_item->ca_labels->ca_label[0]; $va_items[$vs_table . '/' . $vn_id] = array('table' => $vs_table, 'id' => $vn_id, 'idno' => $vs_idno); } print "\t\t[Notice] Found " . sizeof($va_items) . " items\n"; //print_R($va_items); // Ok... now fetch and import each $o_client->setUri($vs_base_url . "/service.php/iteminfo/ItemInfo/rest"); $this->fetchAndImport($va_items, $o_client, $va_source, array(), $vs_code); // TODO: handle deletes // Create new import event ca_data_import_events::newEvent($vn_user_id, 'SYNC', $vs_base_url, 'Sync process synchronization at [' . date("c", $vn_server_timestamp) . ']'); } }
/** * Perform client services-related periodic tasks */ public function hookPeriodicTask(&$pa_params) { $t_log = new Eventlog(); $o_db = new Db(); if (!(bool) $this->opo_config->get('enable_client_services')) { return true; } // Find any orders with status PROCESSED_AWAITING_MEDIA_ACCESS and fetch media $qr_orders = $o_db->query("\n\t\t\t\tSELECT order_id\n\t\t\t\tFROM ca_commerce_orders\n\t\t\t\tWHERE\n\t\t\t\t\torder_status = 'PROCESSED_AWAITING_MEDIA_ACCESS'\n\t\t\t"); // // Set up HTTP client for REST calls // if ($this->opo_client_services_config->get('remote_media_base_url')) { $vs_base_url = $this->opo_client_services_config->get('remote_media_base_url'); $o_client = new RestClient($vs_base_url . "/service.php/iteminfo/ItemInfo/rest"); try { $o_res = $o_client->auth($this->opo_client_services_config->get('remote_media_username'), $this->opo_client_services_config->get('remote_media_password'))->get(); if (!$o_res->isSuccess()) { $t_log->log(array('CODE' => 'ERR', 'MESSAGE' => _t('Could not authenticate to remote system %1', $vs_base_url), 'SOURCE' => 'clientServicesPlugin->hookPeriodicTask')); } while ($qr_orders->nextRow()) { $t_order = new ca_commerce_orders($qr_orders->get('order_id')); $vb_download_errors = false; if ($t_order->getPrimaryKey() && sizeof($va_missing_media = $t_order->itemsMissingDownloadableMedia())) { $va_missing_media_representation_ids = $t_order->itemsMissingDownloadableMedia('original', array('returnRepresentationIDs' => true)); foreach ($va_missing_media as $vn_object_id => $va_representation_md5s) { foreach ($va_representation_md5s as $vn_i => $vs_representation_md5) { $o_xml = $o_client->getObjectRepresentationURLByMD5($vs_representation_md5, 'original')->get(); $vs_url = (string) $o_xml->getObjectRepresentationURLByMD5->original; if (!$vs_url) { continue; } // media no longer exists // fetch the file $t_rep = new ca_object_representations($va_missing_media_representation_ids[$vn_object_id][$vn_i]); if ($t_rep->getPrimaryKey() && ($vs_target_path = $t_rep->getMediaPath('media', 'original'))) { if ($r_source = fopen($vs_url, "rb")) { if ($r_target = fopen($vs_target_path, "wb")) { while (feof($r_source) === false) { fwrite($r_target, fread($r_source, 1024 * 8), 1024 * 8); } fclose($r_target); } else { $vb_download_errors = true; $t_log->log(array('CODE' => 'ERR', 'MESSAGE' => _t('Could not open target path %1', $vs_target_path), 'SOURCE' => 'clientServicesPlugin->hookPeriodicTask')); } fclose($r_source); } else { $vb_download_errors = true; $t_log->log(array('CODE' => 'ERR', 'MESSAGE' => _t('Could not open download URL "%1"', $vs_url), 'SOURCE' => 'clientServicesPlugin->hookPeriodicTask')); } // verify the file was downloaded correctly if (($vs_target_md5 = md5_file($vs_target_path)) !== $vs_representation_md5) { unlink($vs_target_path); $t_log->log(array('CODE' => 'ERR', 'MESSAGE' => _t('Media file %1 failed to be downloaded from url "%2"; checksums differ: %3/%4', $vs_target_path, $vs_url, $vs_representation_md5, $vs_target_md5), 'SOURCE' => 'clientServicesPlugin->hookPeriodicTask')); $vb_download_errors = true; } } else { $t_log->log(array('CODE' => 'ERR', 'MESSAGE' => _t('Invalid representation_id "%1" or target path "%2"', $vn_representation_id, $vs_representation_md5, $vs_target_path), 'SOURCE' => 'clientServicesPlugin->hookPeriodicTask')); $vb_download_errors = true; } } } } if (!$vb_download_errors) { $t_order->setMode(ACCESS_WRITE); $t_order->set('order_status', 'PROCESSED'); $t_order->update(); if ($t_order->numErrors()) { $t_log->log(array('CODE' => 'ERR', 'MESSAGE' => _t('Change of order status to PROCESSED from PROCESSED_AWAITING_MEDIA_ACCESS failed for order_id %1: %2', $t_order->getPrimaryKey(), join('; ', $t_order->getErrors())), 'SOURCE' => 'clientServicesPlugin->hookPeriodicTask')); } } } } catch (Exception $e) { // noop } } // Find any orders with status PROCESSED_AWAITING_DIGITIZATION where all media are now present $qr_orders = $o_db->query("\n\t\t\t\tSELECT order_id\n\t\t\t\tFROM ca_commerce_orders\n\t\t\t\tWHERE\n\t\t\t\t\torder_status = 'PROCESSED_AWAITING_DIGITIZATION'\n\t\t\t"); while ($qr_orders->nextRow()) { $t_order = new ca_commerce_orders($qr_orders->get('order_id')); if ($t_order->getPrimaryKey() && !sizeof($t_order->itemsWithNoDownloadableMedia())) { $t_order->setMode(ACCESS_WRITE); $t_order->set('order_status', 'PROCESSED'); $t_order->update(); if ($t_order->numErrors()) { $t_log->log(array('CODE' => 'ERR', 'MESSAGE' => _t('Change of order status to PROCESSED from PROCESSED_AWAITING_DIGITIZATION failed for order_id %1: %2', $t_order->getPrimaryKey(), join('; ', $t_order->getErrors())), 'SOURCE' => 'clientServicesPlugin->hookPeriodicTask')); } } } // Find orders paid/shipped more than X days ago and mark them as "COMPLETED" $vn_days = (int) $this->opo_client_services_config->get('completed_order_age_threshold'); if ($vn_days > 1) { $vn_threshold = (int) (time() - $vn_days * 24 * 60 * 60); $qr_orders = $o_db->query("\n\t\t\t\t\tSELECT order_id\n\t\t\t\t\tFROM ca_commerce_orders\n\t\t\t\t\tWHERE\n\t\t\t\t\t\t(order_status = 'PROCESSED') \n\t\t\t\t\t\tAND \n\t\t\t\t\t\t((payment_received_on > 0) AND (payment_received_on < ?))\n\t\t\t\t\t\tAND \n\t\t\t\t\t\t(\n\t\t\t\t\t\t\t(shipping_date IS NULL AND shipped_on_date IS NULL)\n\t\t\t\t\t\t\tOR\n\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t(shipped_on_date > 0) AND (shipped_on_date < ?)\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t)\n\t\t\t\t", $vn_threshold, $vn_threshold); while ($qr_orders->nextRow()) { $t_order = new ca_commerce_orders($qr_orders->get('order_id')); if ($t_order->getPrimaryKey()) { $t_order->setMode(ACCESS_WRITE); $t_order->set('order_status', 'COMPLETED'); $t_order->update(); if ($t_order->numErrors()) { $t_log->log(array('CODE' => 'ERR', 'MESSAGE' => _t('Change of order status to COMPLETED from PROCESSED failed for order_id %1: %2', $t_order->getPrimaryKey(), join('; ', $t_order->getErrors())), 'SOURCE' => 'clientServicesPlugin->hookPeriodicTask')); } } } } return true; }