geocoder.drush.inc 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. <?php
  2. /**
  3. * @file
  4. * geocoder.drush.inc
  5. */
  6. /**
  7. * Implements hook_drush_command().
  8. */
  9. function geocoder_drush_command() {
  10. $items = array();
  11. // The key in the $items array is the name of the command.
  12. $items['geocoder-backfill'] = array(
  13. 'callback' => 'geocoder_drush_backfill',
  14. 'description' => 'Geocodes all nodes that have a geocoder widget but no geodata.',
  15. 'options' => array(
  16. 'force' => 'Force the geocode to run, even if there is already geodata',
  17. 'dry' => 'Collect entity ids, but do not update them.',
  18. 'entity_type' => 'An entity type. If none is specified, entities of all types are processed.',
  19. 'field_name' => 'A field name. If none is specified, all applicable fields are processed.',
  20. 'bundle' => 'A bundle name. If none is specified, entities of all bundles are processed.',
  21. 'entity_ids' => 'A list of entity ids, separated by comma (no space). If none are specified, all entities are processed. This requires that entity_type is defined, too.',
  22. ),
  23. );
  24. return $items;
  25. }
  26. /**
  27. * Drush command callback for 'geocoder-backfill'.
  28. */
  29. function geocoder_drush_backfill() {
  30. // Note:
  31. // The values from drush_get_option() are not guaranteed to be in a format one
  32. // might expect, and must be considered unsafe.
  33. // This does not matter for comparisons with ===, but they should not be
  34. // passed to other functions as-is.
  35. $force_reload = drush_get_option('force');
  36. $dry_run = drush_get_option('dry');
  37. $expected_entity_type = drush_get_option('entity_type');
  38. $expected_field_name = drush_get_option('field_name');
  39. $expected_bundle = drush_get_option('bundle');
  40. $expected_entity_ids = drush_get_option_list('entity_ids');
  41. if (!$expected_entity_type) {
  42. if ($expected_bundle) {
  43. drush_log('Cannot specify a bundle, if no entity type is specified.', 'error');
  44. return;
  45. }
  46. if ($expected_entity_ids) {
  47. drush_log('Cannot specify entity ids, if no entity type is specified.', 'error');
  48. return;
  49. }
  50. $expected_bundle = NULL;
  51. $expected_entity_ids = array();
  52. }
  53. foreach (field_info_instances() as $entity_type => $instances_by_bundle) {
  54. if ($expected_entity_type && $entity_type !== $expected_entity_type) {
  55. continue;
  56. }
  57. $entities_to_save = array();
  58. foreach ($instances_by_bundle as $bundle => $instances_by_fieldname) {
  59. if ($expected_bundle && $bundle !== $expected_bundle) {
  60. continue;
  61. }
  62. foreach ($instances_by_fieldname as $dest_field_name => $field_instance) {
  63. if ($expected_field_name && $dest_field_name !== $expected_field_name) {
  64. continue;
  65. }
  66. if ($field_instance['widget']['type'] !== 'geocoder') {
  67. continue;
  68. }
  69. if (empty($field_instance['widget']['settings']['geocoder_field'])) {
  70. continue;
  71. }
  72. $source_field_name = $field_instance['widget']['settings']['geocoder_field'];
  73. // Find source field items without a destination field item.
  74. $q = db_select('field_data_' . $source_field_name, 'source');
  75. $q->condition('source.entity_type', $entity_type);
  76. $q->condition('source.bundle', $bundle);
  77. if ($expected_entity_ids) {
  78. $q->condition('source.entity_id', $expected_entity_ids);
  79. }
  80. if (!$force_reload) {
  81. $q->leftJoin(
  82. 'field_data_' . $dest_field_name,
  83. 'dest',
  84. 'source.entity_type = dest.entity_type and source.entity_id = dest.entity_id');
  85. $q->isNull('dest.entity_id');
  86. }
  87. $q->fields('source', array('entity_id'));
  88. $q->groupBy('source.entity_id');
  89. if (NULL === $result = $q->execute()) {
  90. continue;
  91. }
  92. $etids_orig = $result->fetchCol();
  93. if (array() === $etids_orig) {
  94. drush_log($entity_type . ': ' . $bundle . ': ' . $dest_field_name . ': -', 'ok');
  95. continue;
  96. }
  97. $entities = entity_load($entity_type, $etids_orig);
  98. $etids = array_keys($entities);
  99. $etids_orphan = array_diff($etids, $etids_orig);
  100. drush_log($entity_type . ': ' . $bundle . ': ' . $dest_field_name . ': ' . implode(', ', $etids), 'ok');
  101. if (array() !== $etids_orphan) {
  102. drush_log('Orphan etids: ' . implode(', ', $etids_orphan), 'warning');
  103. }
  104. // Make sure to save every entity only once.
  105. $entities_to_save += $entities;
  106. }
  107. }
  108. if (!$dry_run) {
  109. foreach ($entities_to_save as $entity) {
  110. // Saving an entity automatically triggers recalculation.
  111. entity_save($entity_type, $entity);
  112. }
  113. }
  114. }
  115. }