make.project.inc

  1. 8.0.x commands/make/make.project.inc
  2. 6.x commands/make/make.project.inc
  3. 7.x commands/make/make.project.inc
  4. 5.x commands/make/make.project.inc
  5. master commands/make/make.project.inc

Drush Make processing classes.

Classes

Namesort descending Description
DrushMakeProject The base project class.
DrushMakeProject_Core For processing Drupal core projects.
DrushMakeProject_Library For processing libraries.
DrushMakeProject_Module For processing modules.
DrushMakeProject_Profile For processing installation profiles.
DrushMakeProject_Theme For processing themes.
DrushMakeProject_Translation For processing translations.

File

commands/make/make.project.inc
View source
  1. <?php
  2. /**
  3. * @file
  4. * Drush Make processing classes.
  5. */
  6. use Drush\Log\LogLevel;
  7. /**
  8. * The base project class.
  9. */
  10. class DrushMakeProject {
  11. /**
  12. * TRUE if make() has been called, otherwise FALSE.
  13. */
  14. protected $made = FALSE;
  15. /**
  16. * TRUE if download() method has been called successfully, otherwise FALSE.
  17. */
  18. protected $downloaded = NULL;
  19. /**
  20. * Download location to use.
  21. */
  22. protected $download_location = NULL;
  23. /**
  24. * Keep track of instances.
  25. *
  26. * @see DrushMakeProject::getInstance()
  27. */
  28. protected static $self = array();
  29. /**
  30. * Keeps track of projects being processed to prevent recursive conflicts.
  31. *
  32. * Simple array of machine names.
  33. *
  34. * @var array
  35. */
  36. protected $manifest = array();
  37. /**
  38. * Default to overwrite to allow recursive builds to process properly.
  39. *
  40. * TODO refactor this to be more selective. Ideally a merge would take place
  41. * instead of an overwrite.
  42. */
  43. protected $overwrite = TRUE;
  44. /**
  45. * Recursively process any makefiles found in downloaded projects.
  46. */
  47. protected $do_recursion = TRUE;
  48. /**
  49. * Which variant of profiles to download.
  50. */
  51. protected $variant = 'profile-only';
  52. /**
  53. * Set attributes and retrieve project information.
  54. */
  55. protected function __construct($project) {
  56. $project['base_contrib_destination'] = $project['contrib_destination'];
  57. foreach ($project as $key => $value) {
  58. $this->{$key} = $value;
  59. }
  60. if (!empty($this->options['working-copy'])) {
  61. $this->download['working-copy'] = TRUE;
  62. }
  63. // Don't recurse when we're using a pre-built profile tarball.
  64. if ($this->variant == 'projects') {
  65. $this->do_recursion = FALSE;
  66. }
  67. }
  68. /**
  69. * Get an instance for the type and project.
  70. *
  71. * @param string $type
  72. * Type of project: core, library, module, profile, or translation.
  73. * @param array $project
  74. * Project information.
  75. *
  76. * @return mixed
  77. * An instance for the project or FALSE if invalid type.
  78. */
  79. public static function getInstance($type, $project) {
  80. if (!isset(self::$self[$type][$project['name']])) {
  81. $class = 'DrushMakeProject_' . $type;
  82. self::$self[$type][$project['name']] = class_exists($class) ? new $class($project) : FALSE;
  83. }
  84. return self::$self[$type][$project['name']];
  85. }
  86. /**
  87. * Set the manifest array.
  88. *
  89. * @param array $manifest
  90. * An array of projects as generated by `make_projects`.
  91. */
  92. public function setManifest($manifest) {
  93. $this->manifest = $manifest;
  94. }
  95. /**
  96. * Download a project.
  97. */
  98. function download() {
  99. $this->downloaded = TRUE;
  100. // In some cases, make_download_factory() is going to need to know the
  101. // full version string of the project we're trying to download. However,
  102. // the version is a project-level attribute, not a download-level
  103. // attribute. So, if we don't already have a full version string in the
  104. // download array (e.g. if it was initialized via the release history XML
  105. // for the PM case), we take the version info from the project-level
  106. // attribute, convert it into a full version string, and stuff it into
  107. // $this->download so that the download backend has access to it, too.
  108. if (!empty($this->version) && empty($this->download['full_version'])) {
  109. $full_version = '';
  110. $matches = array();
  111. // Core needs different conversion rules than contrib.
  112. if (!empty($this->type) && $this->type == 'core') {
  113. // Generally, the version for core is already set properly.
  114. $full_version = $this->version;
  115. // However, it might just be something like '7' or '7.x', in which
  116. // case we need to turn that into '7.x-dev';
  117. if (preg_match('/^\d+(\.x)?$/', $this->version, $matches)) {
  118. // If there's no '.x' already, append it.
  119. if (empty($matches[1])) {
  120. $full_version .= '.x';
  121. }
  122. $full_version .= '-dev';
  123. }
  124. }
  125. // Contrib.
  126. else {
  127. // If the version doesn't already define a core version, prepend it.
  128. if (!preg_match('/^\d+\.x-\d+.*$/', $this->version)) {
  129. // Just find the major version from $this->core so we don't end up
  130. // with version strings like '7.12-2.0'.
  131. $core_parts = explode('.', $this->core);
  132. $full_version = $core_parts[0] . '.x-';
  133. }
  134. $full_version .= $this->version;
  135. // If the project-level version attribute is just a number it's a major
  136. // version.
  137. if (preg_match('/^\d+(\.x)?$/', $this->version, $matches)) {
  138. // If there's no '.x' already, append it.
  139. if (empty($matches[1])) {
  140. $full_version .= '.x';
  141. }
  142. $full_version .= '-dev';
  143. }
  144. }
  145. $this->download['full_version'] = $full_version;
  146. }
  147. $this->download['variant'] = $this->variant;
  148. if (make_download_factory($this->name, $this->type, $this->download, $this->download_location) === FALSE) {
  149. $this->downloaded = FALSE;
  150. }
  151. return $this->downloaded;
  152. }
  153. /**
  154. * Build a project.
  155. */
  156. function make() {
  157. if ($this->made) {
  158. drush_log(dt('Attempt to build project @project more then once prevented.', array('@project' => $this->name)));
  159. return TRUE;
  160. }
  161. $this->made = TRUE;
  162. if (!isset($this->download_location)) {
  163. $this->download_location = $this->findDownloadLocation();
  164. }
  165. if ($this->download() === FALSE) {
  166. return FALSE;
  167. }
  168. if (!$this->addLockfile($this->download_location)) {
  169. return FALSE;
  170. }
  171. if (!$this->applyPatches($this->download_location)) {
  172. return FALSE;
  173. }
  174. if (!$this->getTranslations($this->download_location)) {
  175. return FALSE;
  176. }
  177. // Handle .info file re-writing (if so desired).
  178. if (!drush_get_option('no-gitinfofile', FALSE) && isset($this->download['type']) && $this->download['type'] == 'git') {
  179. $this->processGitInfoFiles();
  180. }
  181. // Clean-up .git directories.
  182. if (!_get_working_copy_option($this->download)) {
  183. $this->removeGitDirectory();
  184. }
  185. if (!$this->recurse($this->download_location)) {
  186. return FALSE;
  187. }
  188. return TRUE;
  189. }
  190. /**
  191. * Determine the location to download project to.
  192. */
  193. function findDownloadLocation() {
  194. $this->path = $this->generatePath();
  195. $this->project_directory = !empty($this->directory_name) ? $this->directory_name : $this->name;
  196. $this->download_location = $this->path . '/' . $this->project_directory;
  197. // This directory shouldn't exist yet -- if it does, stop,
  198. // unless overwrite has been set to TRUE.
  199. if (is_dir($this->download_location) && !$this->overwrite) {
  200. return drush_set_error('MAKE_DIRECTORY_EXISTS', dt('Directory not empty: !directory', array('!directory' => $this->download_location)));
  201. }
  202. elseif ($this->download['type'] === 'pm') {
  203. // pm-download will create the final contrib directory.
  204. drush_mkdir(dirname($this->download_location));
  205. }
  206. else {
  207. drush_mkdir($this->download_location);
  208. }
  209. return $this->download_location;
  210. }
  211. /**
  212. * Rewrite relative URLs and file:/// URLs
  213. *
  214. * relative path -> absolute path using the make_directory
  215. * local file:/// urls -> local paths
  216. *
  217. * @param mixed &$info
  218. * Either an array or a simple url string. The `$info` variable will be
  219. * transformed into an array.
  220. */
  221. protected function preprocessLocalFileUrl(&$info) {
  222. if (is_string($info)) {
  223. $info = array('url' => $info, 'local' => FALSE);
  224. }
  225. if (!_drush_is_url($info['url']) && !drush_is_absolute_path($info['url'])) {
  226. $info['url'] = $this->make_directory . '/' . $info['url'];
  227. $info['local'] = TRUE;
  228. } elseif (substr($info['url'], 0, 8) == 'file:///') {
  229. $info['url'] = substr($info['url'], 7);
  230. $info['local'] = TRUE;
  231. }
  232. }
  233. /**
  234. * Retrieve and apply any patches specified by the makefile to this project.
  235. */
  236. function applyPatches($project_directory) {
  237. if (empty($this->patch)) {
  238. return TRUE;
  239. }
  240. $patches_txt = '';
  241. $local_patches = array();
  242. $ignore_checksums = drush_get_option('ignore-checksums');
  243. foreach ($this->patch as $info) {
  244. $this->preprocessLocalFileUrl($info);
  245. // Download the patch.
  246. if ($filename = _make_download_file($info['url'])) {
  247. $patched = FALSE;
  248. $output = '';
  249. // Test each patch style; -p1 is the default with git. See
  250. // http://drupal.org/node/1054616
  251. $patch_levels = array('-p1', '-p0');
  252. foreach ($patch_levels as $patch_level) {
  253. $checked = drush_shell_cd_and_exec($project_directory, 'git --git-dir=. apply --check %s %s --verbose', $patch_level, $filename);
  254. if ($checked) {
  255. // Apply the first successful style.
  256. $patched = drush_shell_cd_and_exec($project_directory, 'git --git-dir=. apply %s %s --verbose', $patch_level, $filename);
  257. break;
  258. }
  259. }
  260. // In some rare cases, git will fail to apply a patch, fallback to using
  261. // the 'patch' command.
  262. if (!$patched) {
  263. foreach ($patch_levels as $patch_level) {
  264. // --no-backup-if-mismatch here is a hack that fixes some
  265. // differences between how patch works on windows and unix.
  266. if ($patched = drush_shell_exec("patch %s --no-backup-if-mismatch -d %s < %s", $patch_level, $project_directory, $filename)) {
  267. break;
  268. }
  269. }
  270. }
  271. if ($output = drush_shell_exec_output()) {
  272. // Log any command output, visible only in --verbose or --debug mode.
  273. drush_log(implode("\n", $output));
  274. }
  275. // Set up string placeholders to pass to dt().
  276. $dt_args = array(
  277. '@name' => $this->name,
  278. '@filename' => basename($filename),
  279. );
  280. if ($patched) {
  281. if (!$ignore_checksums && !_make_verify_checksums($info, $filename)) {
  282. return FALSE;
  283. }
  284. $patch_url = $info['url'];
  285. // If this is a local patch, copy that into place as well.
  286. if ($info['local']) {
  287. $local_patches[] = $info['url'];
  288. // Use a local path for the PATCHES.txt file.
  289. $pathinfo = pathinfo($patch_url);
  290. $patch_url = $pathinfo['basename'];
  291. }
  292. $patches_txt .= '- ' . $patch_url . "\n";
  293. drush_log(dt('@name patched with @filename.', $dt_args), LogLevel::OK);
  294. }
  295. else {
  296. make_error('PATCH_ERROR', dt("Unable to patch @name with @filename.", $dt_args));
  297. }
  298. drush_op('unlink', $filename);
  299. }
  300. else {
  301. make_error('DOWNLOAD_ERROR', 'Unable to download ' . $info['url'] . '.');
  302. return FALSE;
  303. }
  304. }
  305. if (!empty($patches_txt) && !drush_get_option('no-patch-txt') && !file_exists($project_directory . '/PATCHES.txt')) {
  306. $patches_txt = "The following patches have been applied to this project:\n" .
  307. $patches_txt .
  308. "\nThis file was automatically generated by Drush Make (http://drupal.org/project/drush).\n";
  309. file_put_contents($project_directory . '/PATCHES.txt', $patches_txt);
  310. drush_log('Generated PATCHES.txt file for ' . $this->name, LogLevel::OK);
  311. // Copy local patches into place.
  312. foreach ($local_patches as $url) {
  313. $pathinfo = pathinfo($url);
  314. drush_copy_dir($url, $project_directory . '/' . $pathinfo['basename']);
  315. }
  316. }
  317. return TRUE;
  318. }
  319. /**
  320. * Process info files when downloading things from git.
  321. */
  322. function processGitInfoFiles() {
  323. // Bail out if this isn't hosted on Drupal.org (unless --force-gitinfofile option was specified).
  324. if (!drush_get_option('force-gitinfofile', FALSE) && isset($this->download['url']) && strpos($this->download['url'], 'drupal.org') === FALSE) {
  325. return;
  326. }
  327. // Figure out the proper version string to use based on the .make file.
  328. // Best case is the .make file author told us directly.
  329. if (!empty($this->download['full_version'])) {
  330. $full_version = $this->download['full_version'];
  331. }
  332. // Next best is if we have a tag, since those are identical to versions.
  333. elseif (!empty($this->download['tag'])) {
  334. $full_version = $this->download['tag'];
  335. }
  336. // If we have a branch, append '-dev'.
  337. elseif (!empty($this->download['branch'])) {
  338. $full_version = $this->download['branch'] . '-dev';
  339. }
  340. // Ugh. Not sure what else we can do in this case.
  341. elseif (!empty($this->download['revision'])) {
  342. $full_version = $this->download['revision'];
  343. }
  344. // Probably can never reach this case.
  345. else {
  346. $full_version = 'unknown';
  347. }
  348. // If the version string ends in '.x-dev' do the Git magic to figure out
  349. // the appropriate 'rebuild version' string, e.g. '7.x-1.2+7-dev'.
  350. $matches = array();
  351. if (preg_match('/^(.+).x-dev$/', $full_version, $matches)) {
  352. require_once dirname(__FILE__) . '/../pm/package_handler/git_drupalorg.inc';
  353. $rebuild_version = drush_pm_git_drupalorg_compute_rebuild_version($this->download_location, $matches[1]);
  354. if ($rebuild_version) {
  355. $full_version = $rebuild_version;
  356. }
  357. }
  358. require_once dirname(__FILE__) . '/../pm/pm.drush.inc';
  359. if (drush_shell_cd_and_exec($this->download_location, 'git log -1 --pretty=format:%ct')) {
  360. $output = drush_shell_exec_output();
  361. $datestamp = $output[0];
  362. }
  363. else {
  364. $datestamp = time();
  365. }
  366. drush_pm_inject_info_file_metadata($this->download_location, $this->name, $full_version, $datestamp);
  367. }
  368. /**
  369. * Remove the .git directory from a project.
  370. */
  371. function removeGitDirectory() {
  372. if (isset($this->download['type']) && $this->download['type'] == 'git' && file_exists($this->download_location . '/.git')) {
  373. drush_delete_dir($this->download_location . '/.git', TRUE);
  374. }
  375. }
  376. /**
  377. * Add a lock file.
  378. */
  379. function addLockfile($project_directory) {
  380. if (!empty($this->lock)) {
  381. file_put_contents($project_directory . '/.drush-lock-update', $this->lock);
  382. }
  383. return TRUE;
  384. }
  385. /**
  386. * Retrieve translations for this project.
  387. */
  388. function getTranslations($project_directory) {
  389. static $cache = array();
  390. $langcodes = $this->translations;
  391. if ($langcodes && in_array($this->type, array('core', 'module', 'profile', 'theme'), TRUE)) {
  392. // Support the l10n_path, l10n_url keys from l10n_update. Note that the
  393. // l10n_server key is not supported.
  394. if (isset($this->l10n_path)) {
  395. $update_url = $this->l10n_path;
  396. }
  397. else {
  398. if (isset($this->l10n_url)) {
  399. $l10n_server = $this->l10n_url;
  400. }
  401. else {
  402. $l10n_server = FALSE;
  403. }
  404. if ($l10n_server) {
  405. if (!isset($cache[$l10n_server])) {
  406. $this->preprocessLocalFileUrl($l10n_server);
  407. $l10n_server = $l10n_server['url'];
  408. if ($filename = _make_download_file($l10n_server)) {
  409. $server_info = simplexml_load_string(file_get_contents($filename));
  410. $cache[$l10n_server] = !empty($server_info->update_url) ? $server_info->update_url : FALSE;
  411. }
  412. }
  413. if ($cache[$l10n_server]) {
  414. $update_url = $cache[$l10n_server];
  415. }
  416. else {
  417. make_error('XML_ERROR', dt("Could not retrieve l10n update url for !project.", array('!project' => $this->name)));
  418. return FALSE;
  419. }
  420. }
  421. }
  422. if ($update_url) {
  423. $failed = array();
  424. foreach ($langcodes as $langcode) {
  425. $variables = array(
  426. '%project' => $this->name,
  427. '%release' => $this->download['full_version'],
  428. '%core' => $this->core,
  429. '%language' => $langcode,
  430. '%filename' => '%filename',
  431. );
  432. $url = strtr($update_url, $variables);
  433. // Download the translation file. Since its contents are volatile,
  434. // cache for only 4 hours.
  435. if ($filename = _make_download_file($url, 3600 * 4)) {
  436. // If this is the core project type, download the translation file
  437. // and place it in every profile and an additional copy in
  438. // modules/system/translations where it can be detected for import
  439. // by other non-default install profiles.
  440. if ($this->type === 'core') {
  441. $profiles = drush_scan_directory($project_directory . '/profiles', '/.*/', array(), 0, FALSE, 'filename', 0, TRUE);
  442. foreach ($profiles as $profile) {
  443. if (is_dir($project_directory . '/profiles/' . $profile->basename)) {
  444. drush_mkdir($project_directory . '/profiles/' . $profile->basename . '/translations');
  445. drush_copy_dir($filename, $project_directory . '/profiles/' . $profile->basename . '/translations/' . $langcode . '.po');
  446. }
  447. }
  448. drush_mkdir($project_directory . '/modules/system/translations');
  449. drush_copy_dir($filename, $project_directory . '/modules/system/translations/' . $langcode . '.po');
  450. }
  451. else {
  452. drush_mkdir($project_directory . '/translations');
  453. drush_copy_dir($filename, $project_directory . '/translations/' . $langcode . '.po', FILE_EXISTS_OVERWRITE);
  454. }
  455. }
  456. else {
  457. $failed[] = $langcode;
  458. }
  459. }
  460. if (empty($failed)) {
  461. drush_log('All translations downloaded for ' . $this->name, LogLevel::OK);
  462. }
  463. else {
  464. drush_log('Unable to download translations for ' . $this->name . ': ' . implode(', ', $failed), LogLevel::WARNING);
  465. }
  466. }
  467. }
  468. return TRUE;
  469. }
  470. /**
  471. * Generate the proper path for this project type.
  472. *
  473. * @param boolean $base
  474. * Whether include the base part (tmp dir). Defaults to TRUE.
  475. */
  476. protected function generatePath($base = TRUE) {
  477. $path = array();
  478. if ($base) {
  479. $path[] = make_tmp();
  480. $path[] = '__build__';
  481. }
  482. if (!empty($this->contrib_destination)) {
  483. $path[] = $this->contrib_destination;
  484. }
  485. if (!empty($this->subdir)) {
  486. $path[] = $this->subdir;
  487. }
  488. return implode('/', $path);
  489. }
  490. /**
  491. * Return the proper path for dependencies to be placed in.
  492. *
  493. * @return string
  494. * The path that dependencies will be placed in.
  495. */
  496. protected function buildPath($directory) {
  497. return $this->base_contrib_destination;
  498. }
  499. /**
  500. * Recurse to process additional makefiles that may be found during
  501. * processing.
  502. */
  503. function recurse($path) {
  504. if (!$this->do_recursion || drush_get_option('no-recursion')) {
  505. drush_log(dt("Preventing recursive makefile parsing for !project",
  506. array("!project" => $this->name)), LogLevel::INFO);
  507. return TRUE;
  508. }
  509. $candidates = array(
  510. $this->name . '.make.yml',
  511. $this->name . '.make',
  512. 'drupal-org.make.yml',
  513. 'drupal-org.make',
  514. );
  515. $makefile = FALSE;
  516. foreach ($candidates as $filename) {
  517. if (file_exists($this->download_location . '/' . $filename)) {
  518. $makefile = $this->download_location . '/' . $filename;
  519. break;
  520. }
  521. }
  522. if (!$makefile) {
  523. return TRUE;
  524. }
  525. drush_log(dt("Found makefile: !makefile", array("!makefile" => basename($makefile))), LogLevel::OK);
  526. // Save the original state of the 'custom' context.
  527. $custom_context = &drush_get_context('custom');
  528. $original_custom_context_values = $custom_context;
  529. $info = make_parse_info_file($makefile, TRUE, $this->options);
  530. if (!($info = make_validate_info_file($info))) {
  531. $result = FALSE;
  532. }
  533. else {
  534. // Inherit the translations specified in the extender makefile.
  535. if (!empty($this->translations)) {
  536. $info['translations'] = $this->translations;
  537. }
  538. // Strip out any modules that have already been processed before this.
  539. foreach ($this->manifest as $name) {
  540. unset($info['projects'][$name]);
  541. }
  542. $build_path = $this->buildPath($this->name);
  543. make_projects(TRUE, trim($build_path, '/'), $info, $this->build_path, $this->download_location);
  544. make_libraries(TRUE, trim($build_path, '/'), $info, $this->build_path, $this->download_location);
  545. $result = TRUE;
  546. }
  547. // Restore original 'custom' context so that any
  548. // settings changes made are used.
  549. $custom_context = $original_custom_context_values;
  550. return $result;
  551. }
  552. }
  553. /**
  554. * For processing Drupal core projects.
  555. */
  556. class DrushMakeProject_Core extends DrushMakeProject {
  557. /**
  558. * Override constructor for core to adjust project info.
  559. */
  560. protected function __construct(&$project) {
  561. parent::__construct($project);
  562. // subdir and contrib_destination are not allowed for core.
  563. $this->subdir = '';
  564. $this->contrib_destination = '';
  565. }
  566. /**
  567. * Determine the location to download project to.
  568. */
  569. function findDownloadLocation() {
  570. $this->path = $this->download_location = $this->generatePath();
  571. $this->project_directory = '';
  572. if (is_dir($this->download_location)) {
  573. return drush_set_error('MAKE_DIRECTORY_EXISTS', dt('Directory not empty: !directory', array('!directory' => $this->download_location)));
  574. }
  575. elseif ($this->download['type'] === 'pm') {
  576. // pm-download will create the final __build__ directory, so nothing to do
  577. // here.
  578. }
  579. else {
  580. drush_mkdir($this->download_location);
  581. }
  582. return $this->download_location;
  583. }
  584. }
  585. /**
  586. * For processing libraries.
  587. */
  588. class DrushMakeProject_Library extends DrushMakeProject {
  589. /**
  590. * Override constructor for libraries to properly set contrib destination.
  591. */
  592. protected function __construct(&$project) {
  593. parent::__construct($project);
  594. // Allow libraries to specify where they should live in the build path.
  595. if (isset($project['destination'])) {
  596. $project_path = $project['destination'];
  597. }
  598. else {
  599. $project_path = 'libraries';
  600. }
  601. $this->contrib_destination = ($this->base_contrib_destination != '.' ? $this->base_contrib_destination . '/' : '') . $project_path;
  602. }
  603. /**
  604. * No recursion for libraries, sorry :-(
  605. */
  606. function recurse($path) {
  607. // Return TRUE so that processing continues in the make() method.
  608. return TRUE;
  609. }
  610. /**
  611. * No translations for libraries.
  612. */
  613. function getTranslations($download_location) {
  614. // Return TRUE so that processing continues in the make() method.
  615. return TRUE;
  616. }
  617. }
  618. /**
  619. * For processing modules.
  620. */
  621. class DrushMakeProject_Module extends DrushMakeProject {
  622. /**
  623. * Override constructor for modules to properly set contrib destination.
  624. */
  625. protected function __construct(&$project) {
  626. parent::__construct($project);
  627. $this->contrib_destination = ($this->base_contrib_destination != '.' ? $this->base_contrib_destination . '/' : '') . 'modules';
  628. }
  629. }
  630. /**
  631. * For processing installation profiles.
  632. */
  633. class DrushMakeProject_Profile extends DrushMakeProject {
  634. /**
  635. * Override contructor for installation profiles to properly set contrib
  636. * destination.
  637. */
  638. protected function __construct(&$project) {
  639. parent::__construct($project);
  640. $this->contrib_destination = (!empty($this->destination) ? $this->destination : 'profiles');
  641. }
  642. /**
  643. * Find the build path.
  644. */
  645. protected function buildPath($directory) {
  646. return $this->generatePath(FALSE) . '/' . $directory;
  647. }
  648. }
  649. /**
  650. * For processing themes.
  651. */
  652. class DrushMakeProject_Theme extends DrushMakeProject {
  653. /**
  654. * Override contructor for themes to properly set contrib destination.
  655. */
  656. protected function __construct(&$project) {
  657. parent::__construct($project);
  658. $this->contrib_destination = ($this->base_contrib_destination != '.' ? $this->base_contrib_destination . '/' : '') . 'themes';
  659. }
  660. }
  661. /**
  662. * For processing translations.
  663. */
  664. class DrushMakeProject_Translation extends DrushMakeProject {
  665. /**
  666. * Override constructor for translations to properly set contrib destination.
  667. */
  668. protected function __construct(&$project) {
  669. parent::__construct($project);
  670. switch ($project['core']) {
  671. case '5.x':
  672. // Don't think there's an automatic place we can put 5.x translations,
  673. // so we'll toss them in a translations directory in the Drupal root.
  674. $this->contrib_destination = ($this->base_contrib_destination != '.' ? $this->base_contrib_destination . '/' : '') . 'translations';
  675. break;
  676. default:
  677. $this->contrib_destination = '';
  678. break;
  679. }
  680. }
  681. }