/[drupal]/contributions/modules/package_builder/package_builder.module
ViewVC logotype

Contents of /contributions/modules/package_builder/package_builder.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.6 - (show annotations) (download) (as text)
Thu Mar 13 00:26:41 2008 UTC (20 months, 2 weeks ago) by shawnconn
Branch: MAIN
CVS Tags: HEAD
Changes since 1.5: +20 -8 lines
File MIME type: text/x-php
+add bug fix dealing with finding project release; package_builder now iterates over all releases and finds the most recently available link.
+additional typo with text
1 <?php
2 // $Id: package_builder.module,v 1.5 2008/02/09 20:26:26 shawnconn Exp $
3
4 /**
5 * @file
6 * Builds customized Drupal packages
7 *
8 * The package builder module consists mostly of a single form. Users can input
9 * the drupal package, and modules they wish to include in the package. After
10 * entering some further information needed to build a Drupal a profile,
11 * submitting the form will output a bundled tarball that includes drupal, the
12 * specified modules, and the installation profile.
13 *
14 * Module is dependent on PEAR's Archive_Tar and PHP's zlib functions for
15 * handling of tarballs
16 * http://pear.php.net/package/Archive_Tar
17 * http://us2.php.net/manual/en/ref.zlib.php
18 *
19 * Module is dependent on cURL for handle downloading tarballs from drupal.org
20 * http://www.php.net/curl
21 *
22 * Development sponsored by the Ubercart project. http://www.ubercart.org
23 * Written By Shawn Conn. http://www.shawnconn.com/
24 */
25
26 include_once('PEAR.php');
27 include_once ('Archive/Tar.php');
28 define('PACKAGE_BUILDER_EXPIRATION_LENGTH', 86400);
29
30 /*******************************************************************************
31 * Hook Functions (Drupal)
32 *******************************************************************************/
33
34 /**
35 * Implementation of hook_cron().
36 */
37 function package_builder_cron() {
38 $now = time();
39 $projects = db_query("SELECT `checked`, `project_name`,`info` FROM {package_builder_projects} WHERE `module_name` IS NULL");
40 while ($project = db_fetch_object($projects)) {
41 if ($now > $project->checked + PACKAGE_BUILDER_EXPIRATION_LENGTH) {
42 if ($updated_project_info = _package_builder_release_info($project->project_name)) {
43 db_query("UPDATE {package_builder_projects} SET `checked` = %d, `info` = '%s' WHERE `project_name` = '%s' AND `module_name` IS NULL",$now,serialize($updated_project_info),$project->project_name);
44 watchdog('package_builder',t('Project release information has been updated for %project_name',array('%project_name' => $updated_project_info['title'])));
45 }
46 else {
47 $project_info = unserialize($project->info);
48 watchdog('package_builder',t('Failed to retrieve release information for %project_name',array('%project_name' => $project_info['title'])),WATCHDOG_WARNING);
49 }
50 }
51 }
52 }
53
54 /**
55 * Implementation of hook_help().
56 */
57 function package_builder_help($section){
58 switch ($section){
59 case 'admin/build/package':
60 return t('To build your custom Drupal package follow the instructions below.');
61 }
62 }
63
64 /**
65 * Implementation of hook_menu().
66 */
67 function package_builder_menu($may_cache) {
68 if ($may_cache) {
69 $items[] = array(
70 'path' => 'admin/build/package',
71 'title' => t('Package builder'),
72 'access' => user_access('access package builder'),
73 'callback' => 'drupal_get_form',
74 'callback arguments' => array('package_builder_form'),
75 'description' => t('Build a customized Drupal package.'),
76 'type' => MENU_NORMAL_ITEM,
77 );
78 }
79 else {
80 $items[] = array(
81 'path' => 'admin/build/package/delete/'.arg(4),
82 'title' => t('Delete package'),
83 'access' => user_access('access package builder'),
84 'callback' => 'drupal_get_form',
85 'callback arguments' => array('package_builder_delete_form',arg(4)),
86 'description' => t('Delete a specified package.'),
87 'type' => MENU_CALLBACK,
88 );
89 drupal_add_css(drupal_get_path('module', 'package_builder') .'/package_builder.css');
90 }
91 return $items;
92 }
93
94 /**
95 * Implementation of hook_perm().
96 */
97 function package_builder_perm() {
98 return array('access package builder');
99 }
100
101 /*******************************************************************************
102 * Callback Functions, Forms, and Tables
103 *******************************************************************************/
104
105 function theme_package_builder_projects($project) {
106 $output = '<p>'.t('To add projects to the package enter the drupal.org short name (see description below) of the project and click "Add project". Projects will be hightlighted as either <span class="package_builder_module_row">module</span> or <span class="package_builder_theme_row">theme</span> projects. The select box next to the project name will let you choose which project version release to use in the package. Clicking the checkbox next to a module name will enable the module (and its dependent modules) upon installation of the package. Projects can be removed by clicking the checkbox on the right side of the project header.').'</p>';
107 $output .= drupal_render($project['package_project_name']);
108 $output .= drupal_render($project['add_project']);
109 $output .= '<table class="package_builder_project_table"><thead><th colspan="2">'.t('Name').'</th><th>'.t('Version').'</th><th class="package_builder_project_remove" colspan="2">'.t('Remove').'</th></thead><tbody>';
110 foreach ($project as $key => $value) {
111 if ($key[0] != '#' && !is_null($value['version'])) {
112 $project_info = unserialize($project[$key]['info']['#value']);
113 $type = $project[$key]['type']['#value'];
114 $output .= '<tr class="package_builder_'.$type.'_row"><td class="package_builder_project_name" colspan="2">'.l($project_info['title'],"http://drupal.org/project/$key").'</td><td>'.drupal_render($project[$key.'_versions']).'</td><td></td><td class="package_builder_project_remove">'.drupal_render($project[$key.'_remove']).'</td></tr>';
115 if ($type == 'module') {
116 $output .= '<tr class="package_builder_'.$type.'_header"><td colspan="2"></td><td colspan="3"">'.t('Description').'</td></tr>';
117 foreach (array_keys($project['modules_info'][$key]) as $module) {
118 if ($module[0] != '#') {
119 $module_info = unserialize($project['modules_info'][$key][$module]['#value']);
120 $output .= '<tr class="package_builder_'.$type.'_subrow"><td>'.drupal_render($project['modules'][$key][$module.'_install']).'</td><td class="package_builder_module_name">'.$module_info['name'].'</td><td colspan="3" class="description">'.$module_info['description'].'<br/>'.$project['modules'][$key][$module.'_dependencies']['#default_value'].'</td></tr>';
121 }
122 }
123 }
124 }
125 }
126 $output .= '</tbody></table>';
127 $output .= drupal_render($project);
128 return $output;
129 }
130
131 function package_builder_delete_form($package) {
132 $package = urldecode($package);
133 $package_dir = variable_get('file_directory_path','files').'/package_builder';
134 if (is_file("$package_dir/$package")) {
135 $form['package'] = array(
136 '#type' => 'value',
137 '#value' => "$package_dir/$package",
138 );
139 $form = confirm_form($form,t('Delete the package %package_name?',array('%package_name' => $package)),'admin/build/package',t('This action can not be undone.'),t('Yes'),t('No'));
140 }
141 else {
142 drupal_set_message(t('Invalid file'),'error');
143 }
144 return $form;
145 }
146 function package_builder_delete_form_submit($form_id, $form_values) {
147 if (unlink($form_values['package'])) {
148 drupal_set_message(t('%package_name has been deleted',array('%package_name' => basename($form_values['package']))));
149 }
150 drupal_goto('admin/build/package');
151 }
152
153 function package_builder_form() {
154 if (!db_result(db_query("SELECT `version` FROM {package_builder_projects} WHERE `project_name` = 'drupal' AND `module_name` IS NULL"))) {
155 _package_builder_add_project('drupal');
156 }
157 $package_dir = variable_get('file_directory_path','files').'/package_builder';
158 foreach (file_scan_directory($package_dir,".+\.(t|T)(a|A)(r|R)\.(g|G)(z|Z)",array('.', '..', 'CVS'),0,FALSE) as $path => $package) {
159 $packages .= '<li><a href="'.url($path).'">'.basename($path).'</a> ('.t('<a href="!url">delete</a>',array('!url' => url('admin/build/package/delete/'.basename($path)))).')</li>';
160 }
161 $form['existing_packages'] = array(
162 '#type' => 'markup',
163 '#value' => '<div class="package_builder_existing_projects"><strong>'.t('Existing packages:').'</strong><br/><ul>'.$packages.'</ul></div><div class="description">'.t('Previously created packages by the package builder').'</div>',
164 );
165 $form['package_short_name'] = array(
166 '#type' => 'textfield',
167 '#title' => t('Package name'),
168 '#default_value' => variable_get('package_builder_default_short_name','profile'),
169 '#description' => t('The name of the package (may only contain lower case letters and the "_" character)'),
170 '#maxlength' => 50,
171 );
172 $form['project'] = array(
173 '#type' => 'fieldset',
174 '#title' => t('Included projects'),
175 '#collapsible' => TRUE,
176 '#collapsed' => FALSE,
177 );
178 $form['project']['package_project_name'] = array(
179 '#type' => 'textfield',
180 '#title' => t('Project short name'),
181 '#description' => t('The short name of the project to add to the package. This can be found by looking at the project page on <a href="!drupal_url">drupal.org</a>. (e.g. the Drupal project page is http://drupal.org/project/<strong>drupal</strong> thus <strong>drupal</strong> would be the project short name)',array('!drupal_url' => 'http://drupal.org/')),
182 '#maxlength' => 255,
183 );
184 $form['project']['add_project'] = array(
185 '#type' => 'submit',
186 '#value' => t('Add project'),
187 );
188
189 //Load current package projects
190 $projects = db_query("SELECT `project_name`, `version`, `info` FROM {package_builder_projects} WHERE `module_name` IS NULL ORDER BY `project_name` ASC");
191 while ($project = db_fetch_object($projects)) {
192 $info = unserialize($project->info);
193 foreach ($info['releases'] as $version => $release) {
194 $releases[$version] = $version;
195 }
196 $form['project'][$project->project_name]['version'] = array(
197 '#type' => 'value',
198 '#value' => $project->version,
199 );
200 $form['project'][$project->project_name]['info'] = array(
201 '#type' => 'value',
202 '#value' => $project->info,
203 );
204 $form['project'][$project->project_name.'_versions'] = array(
205 '#type' => 'select',
206 '#default_value' => $project->version,
207 '#options' => $releases,
208 '#attributes' => array('onchange' => "document.package_builder_form.submit();"),
209 );
210 if ($project->project_name != 'drupal') {
211 $form['project'][$project->project_name.'_remove'] = array (
212 '#type' => 'checkbox',
213 '#attributes' => array('onchange' => "document.package_builder_form.submit();"),
214 );
215 }
216
217 //Load project modules
218 $modules = db_query("SELECT `module_name`,`info`,`install` FROM {package_builder_projects} WHERE `cache` IS NULL AND `project_name` = '%s'",$project->project_name);
219 $form['project'][$project->project_name]['type'] = array(
220 '#type' => 'value',
221 '#value' => (db_num_rows($modules) == 0) ? 'theme' : 'module',
222 );
223 while ($module = db_fetch_object($modules)) {
224 $module_info = unserialize($module->info);
225 $form['project']['modules'][$project->project_name][$module->module_name.'_install'] = array (
226 '#type' => 'checkbox',
227 '#default_value' => $module->install,
228 );
229 if ($project->project_name == 'drupal' && in_array($module->module_name,_package_builder_required_drupal())) {
230 $form['project']['modules'][$project->project_name][$module->module_name.'_install']['#attributes']['disabled'] = TRUE;
231 }
232 //Check for module dependencies
233 if (!empty($module_info['dependencies'])) {
234 foreach ($module_info['dependencies'] as $dependency) {
235 if ($dependency_info = db_result(db_query("SELECT `info` FROM {package_builder_projects} WHERE `module_name` = '%s'",$dependency))) {
236 $dependency_info = unserialize($dependency_info);
237 $module_dependencies .= $dependency_info['name'].', ';
238 }
239 else {
240 $module_dependencies .= $dependency.t(' (<span class="admin-missing">missing</span>), ');
241 $form['project']['modules'][$project->project_name][$module->module_name.'_install']['#attributes']['disabled'] = TRUE;
242 }
243 }
244 $dependencies = t('<div class="admin-dependencies"><strong>Depends on:</strong> !dependencies</div>',array('!dependencies' => substr($module_dependencies, 0, -2)));
245 unset($module_dependencies);
246 }
247 $form['project']['modules'][$project->project_name][$module->module_name.'_dependencies'] = array (
248 '#type' => 'markup',
249 '#default_value' => $dependencies,
250 );
251 $form['project']['modules_info'][$project->project_name][$module->module_name] = array(
252 '#type' => 'value',
253 '#value' => $module->info,
254 );
255 unset($dependencies);
256 }
257 unset($releases);
258 }
259 $form['project']['#theme'] = 'package_builder_projects';
260
261 //Create profile for package
262 $form['profile'] = array(
263 '#type' => 'fieldset',
264 '#title' => t('Profile'),
265 '#collapsible' => TRUE,
266 '#collapsed' => FALSE,
267 );
268 $form['profile']['help'] = array(
269 '#type' => 'markup',
270 '#value' => '<p>'.t('Drupal <a href="!profile_url">installation profiles</a> allow you to customize your Drupal package further. To finish your package, add a name and description for the profile that will be bundled along with the package. Optionally, you can also add custom PHP code that will be executed after your Drupal package is installed.',array('!profile_url' => 'http://drupal.org/project/Installation+profiles')).'</p>',
271 );
272 $form['profile']['package_name'] = array(
273 '#type' => 'textfield',
274 '#title' => t('Profile name'),
275 '#default_value' => variable_get('package_builder_default_name','Profile'),
276 '#description' => t('The name of the Drupal profile to create.'),
277 '#maxlength' => 100,
278 );
279 $form['profile']['package_description'] = array(
280 '#type' => 'textarea',
281 '#title' => t('Profile description'),
282 '#description' => t("The description of the Drupal package to create."),
283 '#default_value' => variable_get('package_builder_default_description','A profile created by the Drupal Package Builder module.'),
284 '#cols' => 80,
285 '#rows' => 3,
286 );
287 $form['profile']['package_php'] = array(
288 '#type' => 'textarea',
289 '#title' => t('Profile PHP'),
290 '#description' => t("Any PHP code to run after installation of the package and its modules are complete, &lt;?php ?&gt; tags are not needed.<br/><strong>NOTE:</strong> This PHP code isn't evaluated for any syntax or logic errors. It is recommended you test the package installer after building it."),
291 '#default_value' => variable_get('package_builder_last_form_profile_final',""),
292 '#cols' => 80,
293 '#rows' => 20,
294 );
295
296 $form['save_settings'] = array(
297 '#type' => 'submit',
298 '#value' => t('Save settings'),
299 );
300 $form['build_package'] = array(
301 '#type' => 'submit',
302 '#value' => t('Build package'),
303 );
304 $form['#attributes'] = array(
305 'name' => 'package_builder_form'
306 );
307 return $form;
308 }
309 function package_builder_form_validate($form_id, $form_values) {
310 switch ($form_values['op']) {
311 case t('Add project'):
312 if (empty($form_values['package_project_name'])) {
313 form_set_error('package_project_name',t('Project short name is required.'));
314 }
315 elseif (!_package_builder_release_info($form_values['package_project_name'])) {
316 form_set_error('package_project_name',t('Could not retrieve project info for %short_name',array('%short_name' => $form_values['package_project_name'])));
317 }
318 elseif (db_result(db_query("SELECT `version` FROM {package_builder_projects} WHERE `project_name` = '%s' AND `install` IS NULL",$form_values['package_project_name']))) {
319 form_set_error('package_project_name',t('Could not add %short_name, it already has been added to the package',array('%short_name' => $form_values['package_project_name'])));
320 }
321 break;
322 case t('Save settings'):
323 case t('Build package'):
324 if (empty($form_values['package_name'])) {
325 form_set_error('package_name',t('Profile name is required'));
326 }
327 if (empty($form_values['package_description'])) {
328 form_set_error('package_description',t('Profile description is required'));
329 }
330 if (empty($form_values['package_short_name'])) {
331 form_set_error('package_short_name',t('Package short name is required'));
332 }
333 elseif (preg_match('/[^a-z_]/',$form_values['package_short_name'])) {
334 form_set_error('package_short_name',t('Package short name can only contain lower case letters or the "_" character'));
335 }
336 break;
337 default:
338 break;
339 }
340 }
341 function package_builder_form_submit($form_id, $form_values) {
342 switch ($form_values['op']) {
343 case t('Add project'):
344 _package_builder_add_project($form_values['package_project_name']);
345 break;
346 case t('Save settings'):
347 case t('Build package'):
348 foreach ($form_values as $key => $value) {
349 if (substr($key,-8) == '_install' && !in_array(str_replace('_install','',$key),_package_builder_required_drupal())) {
350 db_query("UPDATE {package_builder_projects} SET `install` = %d WHERE `module_name` = '%s'",$value,str_replace('_install','',$key));
351 }
352 }
353 variable_set('package_builder_default_short_name',$form_values['package_short_name']);
354 variable_set('package_builder_default_name',$form_values['package_name']);
355 variable_set('package_builder_default_description',$form_values['package_description']);
356 variable_set('package_builder_last_form_profile_final',$form_values['package_php']);
357 if ($form_values['op'] == t('Build package')) {
358 _package_builder_build_package();
359 }
360 else {
361 drupal_set_message(t('The package settings have been saved'));
362 }
363 break;
364 default: //Check for deleted or updated projects
365 foreach ($form_values as $key => $value) {
366 if (substr($key,-7) == '_remove' && $value) {
367 _package_builder_remove_project(str_replace('_remove','',$key));
368 }
369 if (substr($key,-9) == '_versions') {
370 $project = db_fetch_object(db_query("SELECT * FROM {package_builder_projects} WHERE `project_name` = '%s' AND `install` IS NULL",str_replace('_versions','',$key)));
371 $project_info = unserialize($project->info);
372 if ($project->version != $value && !empty($value)) {
373 _package_builder_remove_project($project->project_name, FALSE);
374 if (_package_builder_add_project($project->project_name, $value, FALSE)) {
375 $project = db_fetch_object(db_query("SELECT * FROM {package_builder_projects} WHERE `project_name` = '%s' AND `install` IS NULL",$project->project_name));
376 $project_info = unserialize($project->info);
377 drupal_set_message(t("Project %project_name has been switched to version %project_version",array('%project_name' => $project_info['title'],'%project_version' => $project->version)));
378 drupal_set_message(t("Project file cached at %file_path",array('%file_path' => $project->cache)));
379 }
380 else {
381 drupal_set_message(t("Project %project_name could not be switched to version %project_version. You will need to add the project again.",array('%project_name' => $project_info['title'],'%project_version' => $value)),'error');
382 }
383 }
384 }
385 }
386 break;
387 }
388 }
389
390 /*******************************************************************************
391 * Module and Helper Functions
392 *******************************************************************************/
393
394 /**
395 * Function adds modules found in a module project into the package_builder table
396 * @param $project
397 * The drupal.org short name of the project
398 */
399 function _package_builder_add_modules($project) {
400 $file_path = db_result(db_query("SELECT cache FROM {package_builder_projects} WHERE project_name = '%s'",$project));
401 $temp_file = variable_get('file_directory_path','files').'/package_builder/tmp';
402 $project_tarball = new Archive_Tar($file_path);
403 $contents = $project_tarball->listContent();
404
405 foreach ($contents as $content) {
406 if (substr($content['filename'],-5) == ".info") {
407 $module = basename($content['filename'],'.info');
408 $enable = ($project == 'drupal' && in_array($module,_package_builder_required_drupal())) ? TRUE : FALSE;
409 $file = $project_tarball->extractInString($content['filename']);
410 file_put_contents($temp_file,$file);
411 $info = _module_parse_info_file($temp_file);
412 unlink($temp_file);
413 db_query("INSERT INTO {package_builder_projects} (`project_name`, `version`, `module_name`, `install`, `info`) VALUES ('%s', '%s', '%s', %d, '%s')",$project,$info['version'],$module,$enable,serialize($info));
414 }
415 }
416 }
417
418 /**
419 * Function adds a project into the package_builder table
420 * @param $project
421 * The drupal.org short name of the project
422 * @param $release
423 * The release version to cache and use for the project
424 * @param $notify
425 * If set to TRUE notifies user of the project addition & cached file
426 * @return:
427 * TRUE if successfully added, FALSE otherwise
428 */
429 function _package_builder_add_project($project, $release = NULL, $notify = TRUE) {
430 $now = time();
431 $package_info = _package_builder_release_info($project);
432 if (is_null($release)) {
433 foreach ($package_info['releases'] as $version => $release) {
434 $download_url = $package_info['releases'][$version]['download_link'];
435 if (!empty($download_url)) {
436 $project_version = $version;
437 break;
438 }
439 }
440 }
441 else {
442 $download_url = $package_info['releases'][$release]['download_link'];
443 $project_version = $release;
444 }
445
446 if ($cache_file = _package_builder_retreive_project($download_url)) {
447 db_query("INSERT INTO {package_builder_projects} (`project_name`, `version`, `checked`, `cache`, `info`) VALUES ('%s', '%s', %d, '%s', '%s')",$project,$project_version,$now,$cache_file,serialize($package_info));
448 if ($notify) {
449 drupal_set_message(t("Project %project_name %project_version has been added to included projects",array('%project_name' => $package_info['title'],'%project_version' => $project_version)));
450 drupal_set_message(t("Project file cached at %file_path",array('%file_path' => $cache_file)));
451 }
452 _package_builder_add_modules($project);
453 return TRUE;
454 }
455 else {
456 form_set_error('package_project_name',t('An error occured in retrieving the project %project_name %project_version from the URL %project_url',array('%project_name' => $project,'%project_url' => $download_url,'%project_version' => $project_version)));
457 return FALSE;
458 }
459 }
460
461 /**
462 * Build a ordered list of modules to enabled based on their dependencies.
463 * @param $list
464 * An existing list of modules to enable
465 * @param $modules
466 * A database query object, containing the columns info & module_name, on the
467 * package_builder table whose rows are the modules to be enabled.
468 * @return:
469 * An ordered array of modules to enable
470 */
471 function _package_builder_build_module_list($list, $modules) {
472 while ($module = db_fetch_object($modules)) {
473 if (!in_array($module->module_name,$list)) {
474 $module_info = unserialize($module->info);
475 if (!empty($module_info['dependencies'])) {
476 foreach ($module_info['dependencies'] as $dependency) {
477 if (!in_array($dependency,$list)) {
478 $other_dependencies = _package_builder_get_dependencies($dependency);
479 if (!empty($other_dependencies)) {
480 foreach ($other_dependencies as $new_dependency) {
481 if (!in_array($new_dependency,$list)) {
482 $list[] = $new_dependency;
483 }
484 }
485 }
486 $list[] = $dependency;
487 }
488 }
489 }
490 $list[] = $module->module_name;
491 }
492 }
493 return $list;
494 }
495
496 /**
497 * Build a drupal installation profile
498 * @param $notify
499 * If set to TRUE, notifies user of the package creation
500 */
501 function _package_builder_build_package($notify = TRUE) {
502 include_once ('Archive/Tar.php');
503
504 $profile_name = variable_get('package_builder_default_short_name','profile');
505 $temp_dir = file_directory_temp().'/package_builder_'.md5($_SERVER['REMOTE_ADDR'].time());
506 $package_tarball = variable_get('file_directory_path','files')."/package_builder/$profile_name.tar.gz";
507 $temp_tarball = tempnam(file_directory_temp(),'package_builder');
508 $package = new Archive_Tar($temp_tarball,TRUE);
509 mkdir($temp_dir);
510
511 $drupal_tarball = db_result(db_query("SELECT `cache` FROM {package_builder_projects} WHERE `install` IS NULL AND `project_name` = 'drupal'"));
512 $drupal_package = new Archive_Tar($drupal_tarball);
513 $drupal_package->extractModify($temp_dir, basename($drupal_tarball, ".tar.gz"));
514 mkdir("$temp_dir/sites/all/modules");
515 mkdir("$temp_dir/sites/all/themes");
516 mkdir("$temp_dir/profiles/$profile_name");
517
518 $projects = db_query("SELECT `project_name`, `cache` FROM {package_builder_projects} WHERE `module_name` IS NULL AND `project_name` <> 'drupal'");
519 while ($project = db_fetch_object($projects)) {
520 $modules = db_result(db_query("SELECT COUNT(*) FROM {package_builder_projects} WHERE `project_name` = '%s' AND `cache` IS NULL",$project->project_name));
521 $dump_dir = ($modules == 0) ? "$temp_dir/sites/all/themes" : "$temp_dir/sites/all/modules";
522 $project_tarball = new Archive_Tar($project->cache);
523 $project_tarball->extractModify($dump_dir,'');
524 }
525 file_put_contents("$temp_dir/profiles/$profile_name/$profile_name.profile",_package_builder_build_profile($profile_name));
526
527 $package_files = _package_builder_read_dir($temp_dir);
528 $package->addModify($package_files,"$profile_name/",$temp_dir);
529 file_copy($temp_tarball,$package_tarball,FILE_EXISTS_REPLACE);
530 if ($notify) {
531 drupal_set_message(t('The package has been placed at <a href="!package_url">!package_name</a>',array('!package_url' => base_path().$package_tarball, '!package_name' => basename($package_tarball))));
532 }
533 }
534
535 /**
536 * Build a drupal installation profile
537 * @param $profile
538 * The name of the .profile installation profile to be generated
539 * @return:
540 * The contents of the .profile installation profile to be dumped into a file.
541 */
542 function _package_builder_build_profile($profile) {
543 $profile_name = str_replace("'","\\'",variable_get('package_builder_default_name','Profile'));
544 $profile_description = str_replace("'","\\'",variable_get('package_builder_default_description','A profile created by the Drupal Package Builder module.'));
545 $profile_php = variable_get('package_builder_last_form_profile_final',"");
546 $module_list = _package_builder_required_drupal();
547
548 $drupal_modules = db_query("SELECT `module_name`,`info` FROM {package_builder_projects} WHERE `cache` IS NULL AND `project_name` = 'drupal' AND `install` = 1");
549 $module_list = _package_builder_build_module_list($module_list,$drupal_modules);
550 $other_modules = db_query("SELECT `module_name`,`info` FROM {package_builder_projects} WHERE `cache` IS NULL AND `project_name` <> 'drupal' AND `install` = 1");
551 $module_list = _package_builder_build_module_list($module_list,$other_modules);
552
553 foreach ($module_list as $index => $module) {
554 $module_list[$index] = "'$module'";
555 }
556 $installed_modules = implode(',',$module_list);
557
558 return "<?php
559 // Custom profile generated by package_builder module
560
561 /**
562 * Return an array of the modules to be enabled when this profile is installed.
563 *
564 * @return
565 * An array of modules to be enabled.
566 */
567 function ".$profile."_profile_modules() {
568 return array($installed_modules);
569 }
570
571 /**
572 * Return a description of the profile for the initial installation screen.
573 *
574 * @return
575 * An array with keys 'name' and 'description' describing this profile.
576 */
577 function ".$profile."_profile_details() {
578 return array(
579 'name' => '$profile_name',
580 'description' => '$profile_description'
581 );
582 }
583
584 /**
585 * Perform any final installation tasks for this profile.
586 *
587 * @return
588 * An optional HTML string to display to the user on the final installation
589 * screen.
590 */
591 function ".$profile."_profile_final() {
592 $profile_php
593 }";
594 }
595
596 /**
597 * Get a list of dependencies (and their recursive dependencies) for a given
598 * module
599 * @param $module
600 * The name of the module to get the dependencies of.
601 * @return:
602 * An array containing the module's dependencies
603 */
604 function _package_builder_get_dependencies($module) {
605 $output = array();
606 if ($module_info = db_result(db_query("SELECT `info` FROM {package_builder_projects} WHERE `module_name` = '%s'",$module))) {
607 $module_info = unserialize($module_info);
608 if (!empty($module_info['dependencies'])) {
609 foreach ($module_info['dependencies'] as $dependency) {
610 $other_dependencies = _package_builder_get_dependencies($dependency);
611 if (!empty($other_dependencies)) {
612 $output = $output + $other_dependencies;
613 }
614 $output[] = $dependency;
615 }
616 }
617 }
618 return $output;
619 }
620
621 /**
622 * A simplified version of Drupal's file_scan_directory that reads a dir and
623 * returns the all the files and directories contained within (including files
624 * that "." charcaters
625 * @param $dir
626 * The directory path to read
627 * @return:
628 * An array of files contained within the directory
629 */
630 function _package_builder_read_dir($dir) {
631 $files = array();
632 if (is_dir($dir) && $handle = opendir($dir)) {
633 while ($file = readdir($handle)) {
634 if ($file != '.' && $file != '..') {
635 if (is_dir("$dir/$file")) {
636 $files = array_merge($files,_package_builder_read_dir("$dir/$file"));
637 }
638 else {
639 $files[] = "$dir/$file";
640 }
641 }
642 }
643 closedir($handle);
644 }
645 return $files;
646 }
647
648 /**
649 * Function returns list of required modules for Drupal core
650 * @return:
651 * An array of module names that make up Drupal core
652 */
653 function _package_builder_required_drupal() {
654 return array('block', 'filter', 'node', 'system', 'user', 'watchdog');
655 }
656
657 /**
658 * Function retrieves release info of project off of drupal.org
659 * @param $project
660 * The drupal.org short name of the project
661 * @return:
662 * The parsed XML data or FALSE if release information couldn't be retrieved
663 */
664 function _package_builder_release_info($project) {
665 $url = UPDATE_STATUS_DEFAULT_URL.'/'.$project.'/'.UPDATE_STATUS_CORE_VERSION;
666 $xml = drupal_http_request($url);
667 $parser = new update_status_xml_parser;
668 $data[] = $xml->data;
669
670 if ($data) {
671 $parsed = $parser->parse($data);
672 return $parsed[$project];
673 }
674 else {
675 return FALSE;
676 }
677 }
678
679 /**
680 * Function removes a project from the package_builder table
681 * @param $project
682 * The drupal.org short name of the project
683 * @param $notify
684 * If set to TRUE notifies user of the project & cached file deletion
685 */
686 function _package_builder_remove_project($project, $notify = TRUE) {
687 $removed_project = db_fetch_object(db_query("SELECT * FROM {package_builder_projects} WHERE `project_name` = '%s' AND `install` IS NULL",$project));
688 $project_info = unserialize($removed_project->info);
689 db_query("DELETE FROM {package_builder_projects} WHERE `project_name` = '%s'",$removed_project->project_name);
690 unlink($removed_project->cache);
691
692 if ($notify) {
693 drupal_set_message(t("Project %project_name has been removed from included projects",array('%project_name' => $project_info['title'])));
694 drupal_set_message(t("Project file cache at %file_path has been removed",array('%file_path' => $removed_project->cache)));
695 }
696 }
697
698 /**
699 * Function retrieves a release tarball from a specified URL
700 * @param $url
701 * The URL to retrieve the tarball from
702 * @return:
703 * A string containing the file path of the tarball or FALSE if the file could
704 * not be retrieved.
705 */
706 function _package_builder_retreive_project($url) {
707 $file_dir = variable_get('file_directory_path','files').'/package_builder/cache';
708 file_check_directory($file_dir, TRUE);
709 $file_path = $file_dir.'/'.basename($url);
710 $curl_handle = curl_init($url);
711 $new_file = @fopen($file_path, "w");
712 @curl_setopt($curl_handle, CURLOPT_FILE, $new_file);
713 @curl_setopt($curl_handle, CURLOPT_HEADER, 0);
714 @curl_setopt($curl_handle, CURLOPT_CONNECTTIMEOUT, 20);
715 $output = (@curl_exec($curl_handle)) ? $file_path : FALSE;
716 @fclose($new_file);
717 return $output;
718 }

  ViewVC Help
Powered by ViewVC 1.1.2