View source
<?php
namespace HookUpdateDeployTools;
class Terms implements ImportInterface, ExportInterface {
public static function import($vocabulary_term_names) {
$t = get_t();
$completed = array();
$vocabulary_term_names = (array) $vocabulary_term_names;
$total_requested = count($vocabulary_term_names);
try {
Check::notEmpty('$vocabulary_term_names', $vocabulary_term_names);
self::canImport();
foreach ($vocabulary_term_names as $key => $vocabulary_term_name) {
$vocabulary_name = self::getVocabularyName($vocabulary_term_name);
$term_name = self::getTermName($vocabulary_term_name);
$filename = self::normalizeFileName($vocabulary_term_name);
if (HudtInternal::canReadFile($filename, 'term')) {
$file_contents = HudtInternal::readFileToString($filename, 'term');
eval('$term_import = ' . $file_contents . ';');
if (!is_object($term_import)) {
if (empty($errors)) {
$errors = 'Term build error on eval().';
}
$message = 'Unable to get a term from the import. Errors: @errors';
throw new HudtException($message, array(
'@errors' => $errors,
), WATCHDOG_ERROR);
}
$error_msg = '';
$result = self::importOne($term_import, $vocabulary_name, $term_name);
$message = '@operation: @vterm - successful.';
global $base_url;
$link = "{$base_url}/{$result['edit_link']}";
$vars = array(
'@operation' => $result['operation'],
'@vterm' => "{$vocabulary_name}:{$term_name}",
);
Message::make($message, $vars, WATCHDOG_INFO, 1, $link);
$completed["{$vocabulary_name}:{$term_name}"] = $result['operation'];
}
}
} catch (\Exception $e) {
$vars = array(
'!error' => method_exists($e, 'logMessage') ? $e
->logMessage() : $e
->getMessage(),
);
if (!method_exists($e, 'logMessage')) {
$message = 'Term import denied because: !error';
Message::make($message, $vars, WATCHDOG_ERROR);
}
$done = HudtInternal::getSummary($completed, $total_requested, 'Imported');
Message::make($done, array(), FALSE, 1);
throw new HudtException('Caught Exception: Update aborted! !error', $vars, WATCHDOG_ERROR, FALSE);
}
$done = HudtInternal::getSummary($completed, $total_requested, 'Imported Terms');
return $done;
}
public static function canImport() {
Check::canUse('taxonomy');
return TRUE;
}
public static function canExport() {
$file = DRUPAL_ROOT . '/includes/utility.inc';
require_once $file;
Check::canUse('taxonomy');
return TRUE;
}
public static function delete($term_name, $vocabulary_name) {
try {
Check::canUse('taxonomy');
Check::canCall('taxonomy_term_delete');
Check::notEmpty('$term_name', $term_name);
Check::notEmpty('$vocabulary_name', $vocabulary_name);
$vars = array(
'@term_name' => $term_name,
'@vocabulary_name' => $vocabulary_name,
);
$term = self::loadByName($term_name, $vocabulary_name, FALSE);
if (empty($term)) {
$vars['@exists_text'] = "does not exist";
$vars['@action_taken'] = "so was not deleted. Skipping Terms::delete";
}
else {
$vars['@tid'] = $term->tid;
$vars['@exists_text'] = "exists";
$delete_status = taxonomy_term_delete($term->tid);
$vars['@deleted_status'] = $delete_status;
if ($delete_status === SAVED_DELETED) {
$vars['@action_taken'] = "was deleted";
$term = self::loadByName($term_name, $vocabulary_name, FALSE);
if (!empty($term)) {
$message = "Deleting the Term '@vocabulary_name:@term_name' did no go as expected. It @action_taken but still @exists_text.";
throw new HudtException($message, $vars, WATCHDOG_ERROR, TRUE);
}
}
else {
$message = "Deleting the Term '@vocabulary_name:@term_name' did not go as expected. Status:'@deleted_status'";
throw new HudtException($message, $vars, WATCHDOG_ERROR, TRUE);
}
}
} catch (\Exception $e) {
$vars['!error'] = method_exists($e, 'logMessage') ? $e
->logMessage() : $e
->getMessage();
if (!method_exists($e, 'logMessage')) {
$message = "Terms::delete Term '@vocabulary_name:@term_name' failed because: !error";
Message::make($message, $vars, WATCHDOG_ERROR);
}
throw new HudtException('Caught Exception: Update aborted! !error', $vars, WATCHDOG_ERROR, FALSE);
}
$return_msg = Message::make("Term @vocabulary_name:@term_name(@tid) @exists_text @action_taken.", $vars, WATCHDOG_INFO, 1);
return $return_msg;
}
private static function getTermName($vocabulary_term_name) {
$parts = explode('|', $vocabulary_term_name);
$term_name = !empty($parts[1]) ? $parts[1] : '';
Check::notEmpty('$term_name', $term_name);
return $term_name;
}
private static function getVocabularyName($vocabulary_term_name) {
$parts = explode('|', $vocabulary_term_name);
$vocabulary_name = !empty($parts[0]) ? $parts[0] : '';
Check::notEmpty('$vocabulary_name', $vocabulary_name);
return $vocabulary_name;
}
private static function normalizeFileName($quasi_name) {
$items = array(
' ' => 'sSs',
'|' => 'zZz',
);
$file_name = str_replace(array_keys($items), array_values($items), $quasi_name);
$file_name = "{$file_name}.txt";
return $file_name;
}
private static function normalizeVocTermName($vocabulary_name, $term_name) {
$items = array(
' ' => 'sSs',
);
$vocabulary_name = str_replace(array_keys($items), array_values($items), $vocabulary_name);
$term_name = str_replace(array_keys($items), array_values($items), $term_name);
return "{$vocabulary_name}zZz{$term_name}";
}
private static function importOne($term_import, $vocabulary_name, $term_name) {
$term_existing = Terms::loadByName($term_name, $vocabulary_name);
$msg_vars = array(
'@vocabulary_name' => $vocabulary_name,
'@term_name' => $term_name,
);
self::unpackParents($term_import);
if (!empty($term_existing)) {
$operation = t('Updated');
$op = 'update';
$saved_term = self::updateExistingTerm($term_import, $term_existing);
}
else {
$operation = t('Created');
$op = 'create';
$saved_term = self::createNewTerm($term_import);
}
$msg_vars['@operation'] = $operation;
switch (TRUE) {
case empty($saved_term->tid):
$message = '@operation of @language: @vocabulary_name : @vocabulary_term failed: The saved term ended up with no tid.';
$valid = FALSE;
break;
case $saved_term->name !== $term_import->name:
$msg_vars['@intended_title'] = $term_import->title;
$msg_vars['@saved_title'] = $saved_term->title;
$message = '@operation failure: The term names do not match. Intended title: @intended_title Saved Title: @saved_title';
$valid = FALSE;
break;
default:
$valid = TRUE;
}
if (!$valid) {
self::rollbackImport($op, $saved_term);
throw new HudtException($message, $msg_vars, WATCHDOG_ERROR, TRUE);
}
$return = array(
'term' => $saved_term,
'operation' => "{$operation}: term/{$saved_term->tid}",
'edit_link' => "taxonomy/term/{$saved_term->tid}/edit",
);
return $return;
}
private static function rollbackImport($op, $term) {
$variables = array(
'@tid' => $term->tid,
'@name' => $term->name,
'@op' => $op,
);
if ($op === 'create') {
if (!empty($term->tid)) {
taxonomy_term_delete($term->tid);
$msg = "Term @name(@tid) was @opd but failed validation and was deleted.";
}
else {
$msg = "The term:@name failed @op and had nothing to roll back.";
}
}
else {
if (!empty($term->original)) {
taxonomy_term_save($term->original);
$msg = "Term @name(@tid) @opd but failed validation, The term was rolled back to its previous state. Verify manually.";
}
else {
$msg = "Term @name(@tid) @opd but failed validation. An original copy was not available to roll back. Verify manually";
}
}
Message::make($msg, $variables, WATCHDOG_INFO, 2);
}
private static function createNewTerm($term) {
$saved_term = clone $term;
unset($saved_term->tid);
$vocabulary = Vocabularies::loadByMachineName($saved_term->vocabulary_machine_name, TRUE);
$saved_term->vid = $vocabulary->vid;
taxonomy_term_save($saved_term);
return $saved_term;
}
private static function updateExistingTerm($term_import, $term_existing) {
$saved_term = clone $term_import;
$saved_term->tid = $term_existing->tid;
taxonomy_term_save($saved_term);
return $saved_term;
}
public static function loadByName($term_name, $vocabulary_name, $strict = FALSE) {
Check::canUse('taxonomy');
Check::canCall('taxonomy_get_term_by_name');
$variables = array(
'@name' => $term_name,
'@vocab' => $vocabulary_name,
);
$vocabulary = Vocabularies::loadByName($vocabulary_name, FALSE);
$vocabulary = !empty($vocabulary) ? $vocabulary : Vocabularies::loadByMachineName($vocabulary_name, FALSE);
if (empty($vocabulary)) {
$message = "There is no Vocabulary '@vocab'. It could not be loaded.";
throw new HudtException($message, $variables, WATCHDOG_ERROR, TRUE);
}
$term = array_shift(taxonomy_get_term_by_name($term_name, $vocabulary->machine_name));
if (!empty($term)) {
return $term;
}
else {
if ($strict) {
$message = "There is no Term '@name'in @vocab. It could not be loaded.";
throw new HudtException($message, $variables, WATCHDOG_ERROR, TRUE);
}
else {
return FALSE;
}
}
}
public static function export($tid) {
$t = get_t();
try {
Check::notEmpty('tid', $tid);
Check::isNumeric('tid', $tid);
self::canExport();
$msg_return = '';
$term = taxonomy_term_load($tid);
Check::notEmpty('term', $term);
Check::notEmpty('term name', $term->name);
Check::notEmpty('vocabulary_machine_name', $term->vocabulary_machine_name);
$vocabulary = Vocabularies::loadByMachineName($term->vocabulary_machine_name, TRUE);
Check::notEmpty('vocabulary_name', $vocabulary->name);
$voc_term_name = self::normalizeVocTermName($vocabulary->name, $term->name);
$file_name = self::normalizeFileName($voc_term_name);
$storage_path = HudtInternal::getStoragePath('term');
$file_uri = DRUPAL_ROOT . '/' . $storage_path . $file_name;
$term->parents = taxonomy_get_parents($tid);
if (!empty($term->path) && isset($term->path['pathauto']) && $term->path['pathauto'] === '0') {
$alias = drupal_get_path_alias("taxonomy/term/{$tid}");
$term->path['alias'] = $alias;
}
$export_contents = drupal_var_export($term);
$msg_return = HudtInternal::writeFile($file_uri, $export_contents);
} catch (\Exception $e) {
$e->logIt = FALSE;
$vars = array(
'!error' => method_exists($e, 'logMessage') ? $e
->logMessage() : $e
->getMessage(),
);
$msg_error = $t("Caught exception: !error", $vars);
}
if (!empty($msg_error)) {
drush_log($msg_error, 'error');
}
return !empty($msg_return) ? $msg_return : $msg_error;
}
private static function unpackParents(&$term_import) {
$new_parents = array();
if (!empty($term_import->parents)) {
foreach ($term_import->parents as $parent) {
$local_parent = self::loadByName($parent->name, $parent->vocabulary_machine_name);
if (empty($local_parent)) {
$variables = array(
'@vocab_name' => $term_import->vocabulary_machine_name,
'@term_name' => $term_import->name,
'@parent_name' => $parent->name,
);
$message = "Import of @vocab_name:@term_name failed because the parent:@parent_name does not exist.";
throw new HudtException($message, $variables, WATCHDOG_ERROR, TRUE);
}
else {
$new_parents[] = $local_parent->tid;
}
}
}
if (!empty($new_parents)) {
$term_import->parent = $new_parents;
}
else {
$term_import->parent = array(
0,
);
}
unset($term_import->parents);
}
}