Config.php

Provision configuration generation classes.

Classes

Namesort descending Description
Provision_Config

File

Provision/Config.php
View source
  1. <?php
  2. /**
  3. * @file
  4. * Provision configuration generation classes.
  5. */
  6. class Provision_Config {
  7. /**
  8. * Template file, a PHP file which will have access to $this and variables
  9. * as defined in $data.
  10. */
  11. public $template = NULL;
  12. /**
  13. * Associate array of variables to make available to the template.
  14. */
  15. public $data = array();
  16. /**
  17. * A Provision_Context object thie configuration relates to.
  18. *
  19. * @var Provision_Context
  20. */
  21. public $context = NULL;
  22. /**
  23. * If set, replaces file name in log messages.
  24. */
  25. public $description = NULL;
  26. /**
  27. * Octal Unix mode for permissons of the created file.
  28. */
  29. protected $mode = NULL;
  30. /**
  31. * Unix group name for the created file.
  32. */
  33. protected $group = NULL;
  34. /**
  35. * An optional data store class to instantiate for this config.
  36. */
  37. protected $data_store_class = NULL;
  38. /**
  39. * The data store.
  40. */
  41. public $store = NULL;
  42. /**
  43. * Forward $this->... to $this->context->...
  44. * object.
  45. */
  46. function __get($name) {
  47. if (isset($this->context)) {
  48. return $this->context->$name;
  49. }
  50. }
  51. /**
  52. * Constructor, overriding not recommended.
  53. *
  54. * @param $context
  55. * An alias name for d(), the Provision_Context that this configuration
  56. * is relevant to.
  57. * @param $data
  58. * An associative array to potentially manipulate in process() and make
  59. * available as variables to the template.
  60. */
  61. function __construct($context, $data = array()) {
  62. if (is_null($this->template)) {
  63. throw new Exception(dt("No template specified for: %class", array('%class' => get_class($this))));
  64. }
  65. // Accept both a reference and an alias name for the context.
  66. $this->context = is_object($context) ? $context : d($context);
  67. if (sizeof($data)) {
  68. $this->data = $data;
  69. }
  70. if (!is_null($this->data_store_class) && class_exists($this->data_store_class)) {
  71. $class = $this->data_store_class;
  72. $this->store = new $class($context, $data);
  73. }
  74. }
  75. /**
  76. * Process and add to $data before writing the configuration.
  77. *
  78. * This is a stub to be implemented by subclasses.
  79. */
  80. function process() {
  81. if (is_object($this->store)) {
  82. $this->data['records'] = array_filter(array_merge($this->store->loaded_records, $this->store->records));
  83. }
  84. return TRUE;
  85. }
  86. /**
  87. * The filename where the configuration is written.
  88. *
  89. * This is a stub to be implemented by subclasses.
  90. */
  91. function filename() {
  92. return FALSE;
  93. }
  94. /**
  95. * Load template from filename().
  96. *
  97. * @see hook_provision_config_load_templates()
  98. * @see hook_provision_config_load_templates_alter()
  99. */
  100. private function load_template() {
  101. // Allow other Drush commands to change the template used first.
  102. $templates = drush_command_invoke_all('provision_config_load_templates', $this);
  103. // Ensure that templates is at least an array.
  104. if (!is_array($templates)) {
  105. $templates = array();
  106. }
  107. // Allow other Drush commands to alter the templates from other commands.
  108. drush_command_invoke_all_ref('provision_config_load_templates_alter', $templates, $this);
  109. if (!empty($templates) && is_array($templates)) {
  110. foreach ($templates as $file) {
  111. if (is_readable($file)) {
  112. drush_log(dt('Template loaded from hook(s): :file'), array(
  113. ':file' => $file,
  114. ));
  115. return file_get_contents($file);
  116. }
  117. }
  118. }
  119. // If we've got this far, then try to find a template from this class or
  120. // one of its parents.
  121. if (isset($this->template)) {
  122. $class_name = get_class($this);
  123. while ($class_name) {
  124. // Iterate through the config file's parent classes until we
  125. // find the template file to use.
  126. $base_dir = provision_class_directory($class_name);
  127. $file = $base_dir . '/' . $this->template;
  128. if (is_readable($file)) {
  129. drush_log(dt('Template loaded from Provision Config class :class_name: :file', array(
  130. ':class_name' => $class_name,
  131. ':file' => $file,
  132. )));
  133. return file_get_contents($file);
  134. }
  135. $class_name = get_parent_class($class_name);
  136. }
  137. }
  138. // We've failed to find a template if we've reached this far.
  139. drush_log(dt('No template found for Provision Config class: ', array(':class' => get_class($this))), 'warning');
  140. return FALSE;
  141. }
  142. /**
  143. * Render template, making variables available from $variables associative
  144. * array.
  145. */
  146. private function render_template($template, $variables) {
  147. drush_errors_off();
  148. extract($variables, EXTR_SKIP); // Extract the variables to a local namespace
  149. ob_start(); // Start output buffering
  150. eval('?>' . $template); // Generate content
  151. $contents = ob_get_contents(); // Get the contents of the buffer
  152. ob_end_clean(); // End buffering and discard
  153. drush_errors_on();
  154. return $contents; // Return the contents
  155. }
  156. /**
  157. * Write out this configuration.
  158. *
  159. * 1. Make sure parent directory exists and is writable.
  160. * 2. Load template with load_template().
  161. * 3. Process $data with process().
  162. * 4. Make existing file writable if necessary and possible.
  163. * 5. Render template with $this and $data and write out to filename().
  164. * 6. If $mode and/or $group are set, apply them for the new file.
  165. */
  166. function write() {
  167. $filename = $this->filename();
  168. // Make directory structure if it does not exist.
  169. if ($filename && !provision_file()->exists(dirname($filename))->status()) {
  170. provision_file()->mkdir(dirname($filename))
  171. ->succeed('Created directory @path.')
  172. ->fail('Could not create directory @path.');
  173. }
  174. $status = FALSE;
  175. if ($filename && is_writeable(dirname($filename))) {
  176. // manipulate data before passing to template.
  177. $this->process();
  178. if ($template = $this->load_template()) {
  179. // Make sure we can write to the file
  180. if (!is_null($this->mode) && !($this->mode & 0200) && provision_file()->exists($filename)->status()) {
  181. provision_file()->chmod($filename, $this->mode | 0200)
  182. ->succeed('Changed permissions of @path to @perm')
  183. ->fail('Could not change permissions of @path to @perm');
  184. }
  185. $status = provision_file()->file_put_contents($filename, $this->render_template($template, $this->data))
  186. ->succeed('Generated config in write(): ' . (empty($this->description) ? $filename : $this->description . ' (' . $filename. ')'), 'success')
  187. ->fail('Could not generate in write(): ' . (empty($this->description) ? $filename : $this->description . ' (' . $filename. ')'))->status();
  188. // Change the permissions of the file if needed
  189. if (!is_null($this->mode)) {
  190. provision_file()->chmod($filename, $this->mode)
  191. ->succeed('Changed permissions of @path to @perm')
  192. ->fail('Could not change permissions of @path to @perm');
  193. }
  194. if (!is_null($this->group)) {
  195. provision_file()->chgrp($filename, $this->group)
  196. ->succeed('Change group ownership of @path to @gid')
  197. ->fail('Could not change group ownership of @path to @gid');
  198. }
  199. }
  200. }
  201. return $status;
  202. }
  203. // allow overriding w.r.t locking
  204. function file_put_contents($filename, $text) {
  205. provision_file()->file_put_contents($filename, $text)
  206. ->succeed('Generated config in file_put_contents()' . (empty($this->description) ? $filename : $this->description), 'success');
  207. }
  208. /**
  209. * Remove configuration file as specified by filename().
  210. */
  211. function unlink() {
  212. return provision_file()->unlink($this->filename())->status();
  213. }
  214. }