features.inc 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. <?php
  2. /**
  3. * @file
  4. * Features module integration.
  5. */
  6. /**
  7. * Implements hook_features_api().
  8. *
  9. * Main info hook that features uses to determine what components are provided
  10. *
  11. * The 'component' for this module is named 'filefield_paths' not just
  12. * 'filefield_paths' to follow recommended practice documented in features.api
  13. *
  14. * We export individual filefield_paths instances, although seldom on their
  15. * own, usually as part of a bigger package. When a content type or field is
  16. * being exported, these settings come along for the ride.
  17. */
  18. function filefield_paths_features_api() {
  19. return array(
  20. 'filefield_paths' => array(
  21. 'name' => t('FileField Paths'),
  22. 'default_hook' => 'default_filefield_paths',
  23. 'feature_source' => TRUE,
  24. 'default_file' => FEATURES_DEFAULTS_INCLUDED_COMMON,
  25. ),
  26. );
  27. }
  28. /**
  29. * Implements hook_features_export_options().
  30. *
  31. * List all FileField Paths config settings currently available for export. This
  32. * adds each of the configurations to the features UI where they can be chosen
  33. * for bundling.
  34. *
  35. * This UI may be entirely unneccessary if we only ever export as a part of
  36. * something else (individual fields settings), but it's here for completeness.
  37. *
  38. * @return array A keyed array of items, suitable for use with a FormAPI select
  39. * or checkboxes element.
  40. */
  41. function filefield_paths_features_export_options() {
  42. $options = array();
  43. $results = db_select('filefield_paths', 'f')
  44. ->fields('f', array('type', 'field'))
  45. ->execute();
  46. foreach ($results as $row) {
  47. // Generate the unique keys that can identify the row
  48. // "{entity_type}::{bundle}::{field_name}" eg "node::story::field_illustration"
  49. $key = "{$row->type}::{$row->field}";
  50. $options[$key] = $key;
  51. }
  52. return $options;
  53. }
  54. /**
  55. * Implements hook_features_export().
  56. *
  57. * Process the export array for a given component.
  58. *
  59. * Normally, we will be adding this as a child in the pipe of
  60. * field_features_export, so that when a filefield instance is exported, this
  61. * setting was published along with it.
  62. */
  63. function filefield_paths_features_export($data, &$export, $module_name = '') {
  64. $export['dependencies']['filefield_paths'] = 'filefield_paths';
  65. $pipe = array();
  66. foreach ($data as $identifier) {
  67. if ($wrapper = filefield_paths_load($identifier)) {
  68. $export['features']['filefield_paths'][$identifier] = $identifier;
  69. if ($wrapper['filename']['transliterate'] || $wrapper['filepath']['transliterate']) {
  70. $export['dependencies']['transliteration'] = 'transliteration';
  71. }
  72. if ($wrapper['filename']['pathauto'] || $wrapper['filepath']['pathauto']) {
  73. $export['dependencies']['pathauto'] = 'pathauto';
  74. }
  75. if (module_exists('strongarm')) {
  76. $variable_map = features_get_default_map('variable');
  77. $pipe['variable'][] = "ffp_{$wrapper['type']}_{$wrapper['field']}";
  78. }
  79. }
  80. }
  81. return $pipe;
  82. }
  83. /**
  84. * Attach our own export routine as a piped export that happens below any
  85. * filefield path that is getting exported.
  86. *
  87. * The component name for fields is 'field'.
  88. *
  89. * HOOK_features_pipe_COMPONENT_alter()
  90. *
  91. * This captures each field export, and adds ourself to the dependencies and
  92. * exports when that field is exported.
  93. */
  94. function filefield_paths_features_pipe_field_alter(&$pipe, $data, $export) {
  95. foreach ($data as $field_identifier) {
  96. // Convert field identifier to FileField Paths format.
  97. $field_identifier = str_replace('-', '::', $field_identifier);
  98. // Field export is exporting a field named $field_identifier.
  99. // If that is a filefield, we should attach ourselves as a subprocess (pipe).
  100. // .. actually, don't need to check the field type,
  101. // just see if we have some filefield_path
  102. // settings that use the same $field_identifier key!
  103. if (filefield_paths_load($field_identifier)) {
  104. // So add this setting as a piped child of the filed when it gets exported.
  105. $pipe['filefield_paths'][$field_identifier] = $field_identifier;
  106. }
  107. }
  108. }
  109. /**
  110. * Return the required path settings for the named filefield instance.
  111. *
  112. * A CRUD utility for filefield_paths
  113. *
  114. * @param a unique identifier for the given field instance -
  115. * {$entity_type::$bundle::$field}.
  116. *
  117. * @return a row array from the filefield_paths DB table - with the 'serialized'
  118. * blobs unpacked.
  119. */
  120. function filefield_paths_load($identifier) {
  121. list($entity_type, $bundle, $field_name) = explode('::', $identifier);
  122. $result = db_select('filefield_paths', 'f')
  123. ->fields('f')
  124. ->condition('type', "{$entity_type}::{$bundle}")
  125. ->condition('field', $field_name)
  126. ->execute();
  127. if ($row = $result->fetchAssoc()) {
  128. $ffp = array();
  129. // Each cell in the row gets exposed, retrieve the schema to figure this out.
  130. $schema = drupal_get_schema('filefield_paths');
  131. foreach ($schema['fields'] as $field => $field_def) {
  132. $ffp[$field] = empty($field_def['serialize']) ? $row[$field] : unserialize($row[$field]);
  133. }
  134. return $ffp;
  135. }
  136. return NULL;
  137. }
  138. /**
  139. * Delete the identified row
  140. *
  141. * A CRUD utility for filefield_paths
  142. */
  143. function filefield_paths_delete($identifier) {
  144. list($entity_type, $bundle, $field_name) = explode('::', $identifier);
  145. db_delete('filefield_paths')
  146. ->condition('type', "{$entity_type}::{$bundle}")
  147. ->condition('field', $field_name)
  148. ->execute();
  149. }
  150. /**
  151. * Implements hook_features_export_render()
  152. *
  153. * Return the PHP code that represents a dump of the settings listed as $data
  154. */
  155. function filefield_paths_features_export_render($module, $data) {
  156. $code = array();
  157. $code[] = ' $settings = array();';
  158. $code[] = '';
  159. $translatables = array();
  160. foreach ($data as $item_id) {
  161. $item = filefield_paths_load($item_id);
  162. if (empty($item)) {
  163. watchdog('filefield_paths', "Failed to retrieve the filefield path settings '%item_id' while preparing the feature export code.", array('%item_id' => $item_id), WATCHDOG_WARNING);
  164. continue;
  165. }
  166. $code[] = " // Exported {$item_id}";
  167. $export = features_var_export($item, ' ');
  168. $code[] = " \$settings['{$item_id}'] = {$export};";
  169. }
  170. $code[] = '';
  171. $code[] = ' return $settings;';
  172. $code = implode("\n", $code);
  173. return array('default_filefield_paths' => $code);
  174. }
  175. /**
  176. * Implements hook_features_export_revert().
  177. */
  178. function filefield_paths_features_revert($module) {
  179. filefield_paths_features_rebuild($module);
  180. }
  181. /**
  182. * Create/recreate the items based on the data array. Data should contain a
  183. * number of filefield_paths definitions.
  184. *
  185. * Implements hook_features_export_rebuild().
  186. *
  187. * Data just need to be put straight into the database as rows.
  188. */
  189. function filefield_paths_features_rebuild($module) {
  190. if ($defaults = features_get_default('filefield_paths', $module)) {
  191. foreach ($defaults as $filefield_paths_id => $filefield_paths) {
  192. // Delete any previous settings for this item.
  193. if (filefield_paths_load($filefield_paths_id)) {
  194. filefield_paths_delete($filefield_paths_id);
  195. }
  196. drupal_write_record('filefield_paths', $filefield_paths);
  197. }
  198. }
  199. }