3 namespace Drupal\Driver\Cores;
5 use Drupal\Driver\Exception\BootstrapException;
10 class Drupal7 extends AbstractCore {
15 public function bootstrap() {
16 // Validate, and prepare environment for Drupal bootstrap.
17 if (!defined('DRUPAL_ROOT')) {
18 define('DRUPAL_ROOT', $this->drupalRoot);
19 require_once DRUPAL_ROOT . '/includes/bootstrap.inc';
20 $this->validateDrupalSite();
25 drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION);
26 if (empty($GLOBALS['databases'])) {
27 throw new BootstrapException('Missing database setting, verify the database configuration in settings.php.');
29 drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
35 public function clearCache() {
36 drupal_flush_all_caches();
42 public function nodeCreate($node) {
43 // Set original if not set.
44 if (!isset($node->original)) {
45 $node->original = clone $node;
48 // Assign authorship if none exists and `author` is passed.
49 if (!isset($node->uid) && !empty($node->author) && ($user = user_load_by_name($node->author))) {
50 $node->uid = $user->uid;
53 // Convert properties to expected structure.
54 $this->expandEntityProperties($node);
56 // Attempt to decipher any fields that may be specified.
57 $this->expandEntityFields('node', $node);
59 // Set defaults that haven't already been set.
60 $defaults = clone $node;
61 node_object_prepare($defaults);
62 $node = (object) array_merge((array) $defaults, (array) $node);
71 public function nodeDelete($node) {
72 node_delete($node->nid);
76 * Implements CoreInterface::runCron().
78 public function runCron() {
79 return drupal_cron_run();
85 public function userCreate(\stdClass $user) {
86 // Default status to TRUE if not explicitly creating a blocked user.
87 if (!isset($user->status)) {
91 // Clone user object, otherwise user_save() changes the password to the
93 $account = clone $user;
95 // Attempt to decipher any fields that may be specified.
96 $this->expandEntityFields('user', $account);
98 user_save($account, (array) $account);
101 $user->uid = $account->uid;
107 public function userDelete(\stdClass $user) {
108 user_cancel(array(), $user->uid, 'user_cancel_delete');
114 public function processBatch() {
115 $batch =& batch_get();
116 $batch['progressive'] = FALSE;
123 public function userAddRole(\stdClass $user, $role_name) {
124 $role = user_role_load_by_name($role_name);
127 throw new \RuntimeException(sprintf('No role "%s" exists.', $role_name));
130 user_multiple_role_edit(array($user->uid), 'add_role', $role->rid);
131 $account = user_load($user->uid);
132 $user->roles = $account->roles;
137 * Check to make sure that the array of permissions are valid.
139 * @param array $permissions
140 * Permissions to check.
142 * Reset cached available permissions.
145 * TRUE or FALSE depending on whether the permissions are valid.
147 protected function checkPermissions(array $permissions, $reset = FALSE) {
148 $available = &drupal_static(__FUNCTION__);
150 if (!isset($available) || $reset) {
151 $available = array_keys(module_invoke_all('permission'));
155 foreach ($permissions as $permission) {
156 if (!in_array($permission, $available)) {
166 public function roleCreate(array $permissions) {
168 // Both machine name and permission title are allowed.
169 $all_permissions = $this->getAllPermissions();
171 foreach ($permissions as $key => $name) {
172 if (!isset($all_permissions[$name])) {
173 $search = array_search($name, $all_permissions);
175 throw new \RuntimeException(sprintf("No permission '%s' exists.", $name));
177 $permissions[$key] = $search;
182 $role = new \stdClass();
183 $role->name = $this->random->name(8);
184 user_role_save($role);
185 user_role_grant_permissions($role->rid, $permissions);
187 if ($role && !empty($role->rid)) {
191 throw new \RuntimeException(sprintf('Failed to create a role with "" permission(s).', implode(', ', $permissions)));
197 public function roleDelete($role_name) {
198 $role = user_role_load_by_name($role_name);
199 user_role_delete((int) $role->rid);
205 public function validateDrupalSite() {
206 if ('default' !== $this->uri) {
207 // Fake the necessary HTTP headers that Drupal needs:
208 $drupal_base_url = parse_url($this->uri);
209 // If there's no url scheme set, add http:// and re-parse the url
210 // so the host and path values are set accurately.
211 if (!array_key_exists('scheme', $drupal_base_url)) {
212 $drupal_base_url = parse_url($this->uri);
215 $drupal_base_url += array(
220 $_SERVER['HTTP_HOST'] = $drupal_base_url['host'];
222 if ($drupal_base_url['port']) {
223 $_SERVER['HTTP_HOST'] .= ':' . $drupal_base_url['port'];
225 $_SERVER['SERVER_PORT'] = $drupal_base_url['port'];
227 if (array_key_exists('path', $drupal_base_url)) {
228 $_SERVER['PHP_SELF'] = $drupal_base_url['path'] . '/index.php';
231 $_SERVER['PHP_SELF'] = '/index.php';
235 $_SERVER['HTTP_HOST'] = 'default';
236 $_SERVER['PHP_SELF'] = '/index.php';
239 $_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_NAME'] = $_SERVER['PHP_SELF'];
240 $_SERVER['REMOTE_ADDR'] = '127.0.0.1';
241 $_SERVER['REQUEST_METHOD'] = NULL;
243 $_SERVER['SERVER_SOFTWARE'] = NULL;
244 $_SERVER['HTTP_USER_AGENT'] = NULL;
246 $conf_path = conf_path(TRUE, TRUE);
247 $conf_file = $this->drupalRoot . "/$conf_path/settings.php";
248 if (!file_exists($conf_file)) {
249 throw new BootstrapException(sprintf('Could not find a Drupal settings.php file at "%s"', $conf_file));
251 $drushrc_file = $this->drupalRoot . "/$conf_path/drushrc.php";
252 if (file_exists($drushrc_file)) {
253 require_once $drushrc_file;
258 * Expands properties on the given entity object to the expected structure.
260 * @param \stdClass $entity
263 protected function expandEntityProperties(\stdClass $entity) {
264 // The created field may come in as a readable date, rather than a
266 if (isset($entity->created) && !is_numeric($entity->created)) {
267 $entity->created = strtotime($entity->created);
270 // Map human-readable node types to machine node types.
271 $types = \node_type_get_types();
272 foreach ($types as $type) {
273 if ($entity->type == $type->name) {
274 $entity->type = $type->type;
283 public function termCreate(\stdClass $term) {
284 // Map vocabulary names to vid, these take precedence over machine names.
285 if (!isset($term->vid)) {
286 $vocabularies = \taxonomy_get_vocabularies();
287 foreach ($vocabularies as $vid => $vocabulary) {
288 if ($vocabulary->name == $term->vocabulary_machine_name) {
289 $term->vid = $vocabulary->vid;
294 if (!isset($term->vid)) {
296 // Try to load vocabulary by machine name.
297 $vocabularies = \taxonomy_vocabulary_load_multiple(FALSE, array(
298 'machine_name' => $term->vocabulary_machine_name,
300 if (!empty($vocabularies)) {
301 $vids = array_keys($vocabularies);
302 $term->vid = reset($vids);
306 // If `parent` is set, look up a term in this vocab with that name.
307 if (isset($term->parent)) {
308 $parent = \taxonomy_get_term_by_name($term->parent, $term->vocabulary_machine_name);
309 if (!empty($parent)) {
310 $parent = reset($parent);
311 $term->parent = $parent->tid;
315 if (empty($term->vid)) {
316 throw new \Exception(sprintf('No "%s" vocabulary found.'));
319 // Attempt to decipher any fields that may be specified.
320 $this->expandEntityFields('taxonomy_term', $term);
322 \taxonomy_term_save($term);
330 public function termDelete(\stdClass $term) {
332 if (isset($term->tid)) {
333 $status = \taxonomy_term_delete($term->tid);
335 // Will be SAVED_DELETED (3) on success.
342 public function languageCreate(\stdClass $language) {
343 if (!module_exists('locale')) {
344 throw new \Exception(sprintf("%s::%s line %s: This driver requires the 'locale' module be enabled in order to create languages", get_class($this), __FUNCTION__, __LINE__));
346 include_once DRUPAL_ROOT . '/includes/iso.inc';
347 include_once DRUPAL_ROOT . '/includes/locale.inc';
349 // Get all predefined languages, regardless if they are enabled or not.
350 $predefined_languages = _locale_get_predefined_list();
352 // If the language code is not valid then throw an InvalidArgumentException.
353 if (!isset($predefined_languages[$language->langcode])) {
354 throw new InvalidArgumentException("There is no predefined language with langcode '{$language->langcode}'.");
357 // Enable a language only if it has not been enabled already.
358 $enabled_languages = locale_language_list();
359 if (!isset($enabled_languages[$language->langcode])) {
360 locale_add_language($language->langcode);
370 public function languageDelete(\stdClass $language) {
371 $langcode = $language->langcode;
372 // Do not remove English or the default language.
373 if (!in_array($langcode, array(language_default('language'), 'en'))) {
374 // @see locale_languages_delete_form_submit().
375 $languages = language_list();
376 if (isset($languages[$langcode])) {
377 // Remove translations first.
378 db_delete('locales_target')
379 ->condition('language', $langcode)
381 cache_clear_all('locale:' . $langcode, 'cache');
382 // With no translations, this removes existing JavaScript translations
384 _locale_rebuild_js($langcode);
385 // Remove the language.
386 db_delete('languages')
387 ->condition('language', $langcode)
390 ->fields(array('language' => ''))
391 ->condition('language', $langcode)
393 if ($languages[$langcode]->enabled) {
394 variable_set('language_count', variable_get('language_count', 1) - 1);
396 module_invoke_all('multilingual_settings_changed');
397 drupal_static_reset('language_list');
400 // Changing the language settings impacts the interface:
401 cache_clear_all('*', 'cache_page', TRUE);
408 public function configGet($name, $key = '') {
409 throw new \Exception('Getting config is not yet implemented for Drupal 7.');
415 public function configSet($name, $key, $value) {
416 throw new \Exception('Setting config is not yet implemented for Drupal 7.');
420 * Helper function to get all permissions.
423 * Array keyed by permission name, with the human-readable title as the
426 protected function getAllPermissions() {
427 $permissions = array();
428 foreach (module_invoke_all('permission') as $name => $permission) {
429 $permissions[$name] = $permission['title'];
437 public function getModuleList() {
438 return module_list();
444 public function getExtensionPathList() {
447 // Get enabled modules.
448 $modules = $this->getModuleList();
449 foreach ($modules as $module) {
450 $paths[] = $this->drupalRoot . DIRECTORY_SEPARATOR . \drupal_get_path('module', $module);
459 public function getEntityFieldTypes($entity_type) {
461 $fields = field_info_field_map();
462 foreach ($fields as $field_name => $field) {
463 if (array_key_exists($entity_type, $field['bundles'])) {
464 $return[$field_name] = $field['type'];
473 public function isField($entity_type, $field_name) {
474 $map = field_info_field_map();
475 return !empty($map[$field_name]) && array_key_exists($entity_type, $map[$field_name]['bundles']);
481 public function clearStaticCaches() {
482 drupal_static_reset();