omega_tools.module 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  1. <?php
  2. /**
  3. * Implements hook_menu().
  4. */
  5. function omega_tools_menu() {
  6. foreach (list_themes() as $theme) {
  7. $items['admin/appearance/settings/' . $theme->name . '/reset'] = array(
  8. 'title' => $theme->info['name'],
  9. 'page callback' => 'drupal_get_form',
  10. 'page arguments' => array('omega_tools_theme_reset_confirm', $theme->name),
  11. 'type' => MENU_CALLBACK,
  12. 'access callback' => '_system_themes_access',
  13. 'access arguments' => array($theme),
  14. 'file' => 'includes/omega_tools.admin.inc',
  15. );
  16. $items['admin/appearance/omega-tools/download/' . $theme->name] = array(
  17. 'title' => $theme->info['name'],
  18. 'page callback' => 'omega_tools_theme_download',
  19. 'page arguments' => array($theme->name),
  20. 'type' => MENU_CALLBACK,
  21. 'access callback' => 'user_access',
  22. 'access arguments' => array('administer themes'),
  23. 'file' => 'includes/omega_tools.admin.inc',
  24. );
  25. $items['admin/appearance/settings/' . $theme->name . '/export'] = array(
  26. 'title' => $theme->info['name'],
  27. 'page callback' => 'drupal_get_form',
  28. 'page arguments' => array('omega_tools_theme_export', $theme->name),
  29. 'type' => MENU_CALLBACK,
  30. 'access callback' => '_system_themes_access',
  31. 'access arguments' => array($theme),
  32. 'file' => 'includes/omega_tools.admin.inc',
  33. );
  34. }
  35. $items['admin/appearance/omega-tools/add'] = array(
  36. 'title' => 'Create new Omega subtheme',
  37. 'page callback' => 'drupal_get_form',
  38. 'page arguments' => array('omega_tools_subtheme_add'),
  39. 'type' => MENU_LOCAL_ACTION,
  40. 'access arguments' => array('administer themes'),
  41. 'file' => 'includes/omega_tools.admin.inc',
  42. 'weight' => 100,
  43. );
  44. $items['admin/appearance/omega-tools/edit/%omega_tools_cache'] = array(
  45. 'title' => 'Configure subtheme',
  46. 'page callback' => 'omega_tools_subtheme_wizard',
  47. 'page arguments' => array(4),
  48. 'type' => MENU_CALLBACK,
  49. 'access callback' => '_omega_tools_theme_access',
  50. 'access arguments' => array(4),
  51. 'file' => 'includes/omega_tools.wizard.inc',
  52. );
  53. $items['admin/appearance/omega-tools/edit/%omega_tools_cache/%'] = $items['admin/appearance/omega-tools/edit/%omega_tools_cache'];
  54. $items['admin/appearance/omega-tools/edit/%omega_tools_cache/%']['page arguments'] = array(4, 5);
  55. return $items;
  56. }
  57. /**
  58. * Implements hook_file_download().
  59. */
  60. function omega_tools_file_download($uri) {
  61. if (strpos(file_uri_target($uri), 'omega-tools/') === 0) {
  62. return array(
  63. 'Content-Type' => file_get_mimetype($uri),
  64. 'Content-Length' => filesize(drupal_realpath($uri)),
  65. 'Content-Disposition' => 'attachment; filename="' . basename($uri) . '"',
  66. );
  67. }
  68. }
  69. /**
  70. * Implements hook_form_FORM_ID_alter().
  71. */
  72. function omega_tools_form_system_theme_settings_alter(&$form, &$form_state) {
  73. $form['#validate'][] = 'omega_tools_theme_settings_form_validate';
  74. $form['actions']['omega_tools_reset'] = array(
  75. '#type' => 'submit',
  76. '#value' => t('Revert theme settings'),
  77. '#submit' => array('omega_tools_theme_settings_form_submit'),
  78. );
  79. $form['actions']['omega_tools_export'] = array(
  80. '#type' => 'submit',
  81. '#value' => t('Export theme settings'),
  82. '#submit' => array('omega_tools_theme_settings_form_submit'),
  83. );
  84. $form['actions']['omega_tools_download'] = array(
  85. '#type' => 'submit',
  86. '#value' => t('Download this theme'),
  87. '#submit' => array('omega_tools_theme_settings_form_submit'),
  88. );
  89. }
  90. /**
  91. * @todo
  92. */
  93. function omega_tools_theme_settings_form_validate($form, &$form_state) {
  94. unset($form_state['values']['omega_tools_reset'], $form_state['values']['omega_tools_export'], $form_state['values']['omega_tools_download']);
  95. }
  96. /**
  97. * @todo
  98. */
  99. function omega_tools_theme_settings_form_submit($form, &$form_state) {
  100. $theme = $form_state['build_info']['args'][0];
  101. unset($form_state['values']['omega_tools_reset'], $form_state['values']['omega_tools_export'], $form_state['values']['omega_tools_download']);
  102. switch ($form_state['triggering_element']['#value']) {
  103. case t('Revert theme settings'):
  104. $form_state['redirect'] = 'admin/appearance/settings/' . $theme . '/reset';
  105. break;
  106. case t('Export theme settings'):
  107. $form_state['redirect'] = 'admin/appearance/settings/' . $theme . '/export';
  108. break;
  109. case t('Download this theme'):
  110. $form_state['redirect'] = 'admin/appearance/omega-tools/download/' . $theme;
  111. break;
  112. }
  113. }
  114. /**
  115. * @todo
  116. */
  117. function omega_tools_cache_load($name) {
  118. return omega_tools_cache_get($name);
  119. }
  120. /**
  121. * @todo
  122. */
  123. function omega_tools_cache_get($name) {
  124. ctools_include('object-cache');
  125. $cache = ctools_object_cache_get('omega_tools', $name);
  126. if (!$cache) {
  127. $themes = list_themes();
  128. if (isset($themes[$name])) {
  129. $path = drupal_get_path('theme', $name);
  130. $info = drupal_parse_info_file($path . '/' . $name . '.info');
  131. $cache = new stdClass();
  132. $cache->new = FALSE;
  133. $cache->machine_name = $name;
  134. $cache->automated = file_prepare_directory($path, NULL) && file_prepare_directory(dirname($path), NULL);
  135. $cache->destination = $path;
  136. $cache->name = $info['name'];
  137. $cache->info = $info;
  138. $cache->status = $themes[$name]->status;
  139. $cache->default = variable_get('theme_default') == $name;
  140. $cache->locked = ctools_object_cache_test('omega_tools', $name);
  141. $cache->path = 'temporary://omega-tools/' . $name . '-' . substr(hash('sha256', serialize($cache) . microtime()), 0, 8);
  142. file_unmanaged_delete_recursive($cache->path);
  143. omega_tools_copy_recursive($cache->destination, $cache->path);
  144. }
  145. }
  146. return $cache;
  147. }
  148. /**
  149. * Store changes to a task handler in the object cache.
  150. */
  151. function omega_tools_cache_set($name, $subtheme) {
  152. ctools_include('object-cache');
  153. ctools_object_cache_set('omega_tools', $name, $subtheme);
  154. }
  155. /**
  156. * Remove an item from the object cache.
  157. */
  158. function omega_tools_cache_clear($name) {
  159. ctools_include('object-cache');
  160. ctools_object_cache_clear('omega_tools', $name);
  161. }
  162. /**
  163. * @todo
  164. */
  165. function omega_tools_system_themes_page_alter(&$info) {
  166. foreach (array('enabled', 'disabled') as $status) {
  167. if (isset($info[$status])) {
  168. foreach ($info[$status] as &$item) {
  169. if (_omega_tools_is_editable($item->name)) {
  170. $item->operations[] = array(
  171. 'title' => t('Edit'),
  172. 'href' => 'admin/appearance/omega-tools/edit/' . $item->name,
  173. 'attributes' => array('title' => t('This theme belongs to the Omega framework and can be edited.')),
  174. );
  175. }
  176. $item->operations[] = array(
  177. 'title' => t('Download'),
  178. 'href' => 'admin/appearance/omega-tools/download/' . $item->name,
  179. 'attributes' => array('title' => t('Download an archive of this theme.')),
  180. );
  181. }
  182. }
  183. }
  184. }
  185. /**
  186. * @todo
  187. */
  188. function omega_tools_base_themes() {
  189. $themes = list_themes();
  190. $options = array();
  191. foreach (array('alpha', 'omega') as $theme) {
  192. if (isset($themes[$theme])) {
  193. $options[$theme] = $themes[$theme]->info['name'];
  194. }
  195. }
  196. foreach ($themes as $theme) {
  197. if (isset($theme->info['base theme']) && empty($theme->info['starterkit'])) {
  198. $base = system_find_base_themes($themes, $theme->name);
  199. if (isset($base['alpha'])) {
  200. $options[$theme->name] = $theme->info['name'];
  201. }
  202. }
  203. }
  204. return $options;
  205. }
  206. /**
  207. * @todo
  208. */
  209. function omega_tools_starterkits($base = NULL) {
  210. $bases = omega_tools_base_themes();
  211. $options = array();
  212. foreach (list_themes() as $name => $theme) {
  213. $info = $theme->info;
  214. if (!empty($info['starterkit']) && isset($info['base theme']) && array_key_exists($info['base theme'], $bases) && ($info['base theme'] == $base || !isset($base))) {
  215. $options[$name] = $info['name'] . '<div class="description">' . $info['description'] . '</div>';
  216. }
  217. }
  218. return $options;
  219. }
  220. /**
  221. * @todo
  222. */
  223. function omega_tools_copy_recursive($source, $destination) {
  224. if (is_dir($source)) {
  225. if (!file_prepare_directory($destination, FILE_CREATE_DIRECTORY)) {
  226. return FALSE;
  227. }
  228. $directory = dir($source);
  229. while (FALSE !== ($read = $directory->read())) {
  230. if ($read != '.' && $read != '..' ) {
  231. if (!omega_tools_copy_recursive($source . '/' . $read, $destination . '/' . $read)) {
  232. return FALSE;
  233. }
  234. }
  235. }
  236. $directory->close();
  237. }
  238. else {
  239. file_unmanaged_copy($source, $destination);
  240. }
  241. return TRUE;
  242. }
  243. /**
  244. * @todo
  245. */
  246. function omega_tools_move($source, $destination) {
  247. if (omega_tools_copy_recursive($source, $destination)) {
  248. file_unmanaged_delete_recursive($source);
  249. return $destination;
  250. }
  251. return FALSE;
  252. }
  253. /**
  254. * @todo
  255. */
  256. function omega_tools_rewrite_recursive($path, $search, $replace, $rename) {
  257. if ($path !== ($new = str_replace($search, $rename, $path))) {
  258. if (!$path = file_unmanaged_move($path, $new, FILE_EXISTS_REPLACE)) {
  259. return FALSE;
  260. };
  261. }
  262. if (is_dir($path)) {
  263. $directory = dir($path);
  264. while (FALSE !== ($read = $directory->read())) {
  265. if ($read != '.' && $read != '..' ) {
  266. if (!omega_tools_rewrite_recursive($path . '/' . $read, $search, $replace, $rename)) {
  267. return FALSE;
  268. }
  269. }
  270. }
  271. $directory->close();
  272. }
  273. else {
  274. omega_tools_replace_contents($path, $search, $replace);
  275. }
  276. return TRUE;
  277. }
  278. /**
  279. * @todo
  280. */
  281. function omega_tools_replace_contents($file, $search, $replace) {
  282. if (is_file($file) && filesize($file) > 0) {
  283. $before = file_get_contents($file);
  284. if ($before != ($after = str_replace($search, $replace, $before))) {
  285. file_unmanaged_save_data($after, $file, FILE_EXISTS_REPLACE);
  286. }
  287. }
  288. }
  289. /**
  290. * @todo
  291. */
  292. function omega_tools_build_info_file($array, $prefix = FALSE) {
  293. $info = '';
  294. foreach ($array as $key => $value) {
  295. if (is_array($value)) {
  296. $info .= omega_tools_build_info_file($value, (!$prefix ? $key : "{$prefix}[{$key}]"));
  297. }
  298. else {
  299. $info .= $prefix ? ("{$prefix}[" . $key .']') : $key;
  300. $info .= " = '" . str_replace("'", "\'", $value) . "'\n";
  301. }
  302. }
  303. return $info;
  304. }
  305. /**
  306. * @todo
  307. */
  308. function omega_tools_write_info_file($name, $info, $destination = NULL) {
  309. $destination = isset($destination) ? $destination : drupal_get_path('theme', $name);
  310. if (!empty($destination)) {
  311. return file_unmanaged_save_data(omega_tools_build_info_file($info), $destination . '/' . $name . '.info', FILE_EXISTS_REPLACE);
  312. }
  313. return FALSE;
  314. }
  315. /**
  316. * @todo
  317. */
  318. function omega_tools_subtheme_create(&$subtheme) {
  319. if (is_dir($subtheme->path)) {
  320. file_unmanaged_delete_recursive($subtheme->path);
  321. }
  322. if (!file_prepare_directory($subtheme->path, FILE_CREATE_DIRECTORY)) {
  323. drupal_set_message(t('Omega Tools could not create the directory %dir.', array('%dir' => $subtheme->path)), 'error');
  324. watchdog('Omega Tools', t('Omega Tools could not create the directory %dir.', array('%dir' => $subtheme->path)), array(), WATCHDOG_ERROR);
  325. return FALSE;
  326. }
  327. if ($subtheme->starterkit) {
  328. if (!omega_tools_copy_recursive(drupal_get_path('theme', $subtheme->starterkit), $subtheme->path)) {
  329. $themes = list_themes();
  330. drupal_set_message(t('Omega Tools could not copy the starterkit %starterkit.', array('%starterkit' => $themes[$subtheme->starterkit]->info['name'])), 'error');
  331. watchdog('Omega Tools', t('Omega Tools could not copy the starterkit %starterkit.', array('%starterkit' => $themes[$subtheme->starterkit]->info['name'])), array(), WATCHDOG_ERROR);
  332. return FALSE;
  333. }
  334. $subtheme->info = drupal_parse_info_file($subtheme->path . '/' . $subtheme->starterkit . '.info');
  335. file_unmanaged_delete($subtheme->path . '/' . $subtheme->starterkit . '.info');
  336. }
  337. else {
  338. if (!omega_tools_copy_recursive(drupal_get_path('module', 'omega_tools') . '/default', $subtheme->path)) {
  339. drupal_set_message(t('Omega Tools could not copy the default pattern.'), 'error');
  340. watchdog('Omega Tools', t('Omega Tools could not copy the default pattern.'), array(), WATCHDOG_ERROR);
  341. return FALSE;
  342. }
  343. $base = drupal_parse_info_file(drupal_get_path('theme', $subtheme->base) . '/' . $subtheme->base . '.info');
  344. $subtheme->info = drupal_parse_info_file($subtheme->path . '/default.pattern');
  345. $subtheme->info['regions'] = isset($base['regions']) ? $base['regions'] : array();
  346. $subtheme->info['zones'] = isset($base['zones']) ? $base['zones'] : array();
  347. $subtheme->info['settings'] = isset($base['settings']) ? $base['settings'] : array();
  348. file_unmanaged_delete($subtheme->path . '/default.pattern');
  349. }
  350. unset($subtheme->info['starterkit'], $subtheme->info['hidden'], $subtheme->info['locked'], $subtheme->info['project'], $subtheme->info['datestamp']);
  351. $subtheme->info['name'] = $subtheme->name;
  352. $subtheme->info['description'] = '';
  353. $subtheme->info['base theme'] = $subtheme->base;
  354. $subtheme->info['engine'] = 'phptemplate';
  355. $subtheme->info['core'] = DRUPAL_CORE_COMPATIBILITY;
  356. $subtheme->info['version'] = '1.x';
  357. $subtheme->info['screenshot'] = 'screenshot.png';
  358. $subtheme->info['regions'] = array_merge(_omega_tools_core_regions(), $subtheme->info['regions']);
  359. $subtheme->info['zones'] = array_merge(_omega_tools_default_zones(), $subtheme->info['zones']);
  360. omega_tools_write_info_file($subtheme->machine_name, $subtheme->info, $subtheme->path);
  361. omega_tools_rewrite_recursive($subtheme->path, 'YOURTHEME', $subtheme->machine_name, str_replace('_', '-', $subtheme->machine_name));
  362. drupal_set_message(t('You have successfully created the theme %name.', array('%name' => $subtheme->name)));
  363. return TRUE;
  364. }
  365. /**
  366. * @todo
  367. */
  368. function omega_tools_subtheme_process($subtheme) {
  369. drupal_theme_rebuild();
  370. system_rebuild_theme_data();
  371. if ($subtheme->status) {
  372. theme_enable(array($subtheme->machine_name));
  373. if ($subtheme->default) {
  374. variable_set('theme_default', $subtheme->machine_name);
  375. drupal_set_message(t('%name is now the default theme.', array('%name' => $subtheme->name)));
  376. }
  377. }
  378. else {
  379. theme_disable(array($subtheme->machine_name));
  380. }
  381. }
  382. /**
  383. * @todo
  384. */
  385. function omega_tools_sites() {
  386. $sites = &drupal_static(__FUNCTION__);
  387. if (!isset($sites)) {
  388. $sites = array();
  389. if (file_exists(DRUPAL_ROOT . '/sites/sites.php')) {
  390. include(DRUPAL_ROOT . '/sites/sites.php');
  391. }
  392. $sites = array('all') + array_values($sites);
  393. }
  394. return $sites;
  395. }
  396. /**
  397. * @todo
  398. */
  399. function omega_tools_sites_options() {
  400. $options = array();
  401. if ($sites = omega_tools_sites()) {
  402. $options += array_combine($sites, $sites);
  403. }
  404. $options['all'] = t('Default destination (all)');
  405. return $options;
  406. }
  407. /**
  408. * @todo
  409. */
  410. function omega_tools_write_archive($source, $name, $destination = NULL) {
  411. $destination = isset($destination) ? $destination : 'temporary://omega-tools';
  412. if (!file_prepare_directory($destination, FILE_CREATE_DIRECTORY)) {
  413. drupal_set_message(t('Omega Tools could not create the directory %dir', array('%dir' => $destination)), 'error');
  414. watchdog('Omega Tools', t('Omega Tools could not create the directory %dir', array('%dir' => $destination)), array(), WATCHDOG_ERROR);
  415. return FALSE;
  416. }
  417. $destination = $destination . '/' . $name . '.tar';
  418. $current = getcwd();
  419. chdir(drupal_realpath(dirname($source)));
  420. $archiver = new Archive_Tar(drupal_realpath($destination));
  421. $archiver->create(basename(rtrim($source, '/')));
  422. chdir($current);
  423. return $destination;
  424. }
  425. /**
  426. * @todo
  427. */
  428. function omega_tools_revert_theme_settings($theme) {
  429. $themes = list_themes();
  430. variable_del('theme_' . $theme . '_settings');
  431. drupal_theme_rebuild();
  432. system_rebuild_theme_data();
  433. watchdog('theme', t('Theme settings for %theme reset to default values.', array('%theme' => $themes[$theme]->info['name'])));
  434. drupal_set_message(t('The theme settings for %theme have been purged from the database and are now being loaded from the .info file of this theme.', array('%theme' => $themes[$theme]->info['name'])));
  435. }
  436. /**
  437. * @todo
  438. */
  439. function _omega_tools_core_regions() {
  440. return array(
  441. 'page_top' => 'Page Top',
  442. 'page_bottom' => 'Page Bottom',
  443. 'content' => 'Content',
  444. );
  445. }
  446. /**
  447. * @todo
  448. */
  449. function _omega_tools_default_zones() {
  450. return array(
  451. 'header' => 'Header',
  452. 'content' => 'Content',
  453. 'footer' => 'Footer',
  454. );
  455. }
  456. /**
  457. * @todo
  458. */
  459. function _omega_tools_theme_exists($theme) {
  460. $themes = list_themes();
  461. return isset($themes[$theme]);
  462. }
  463. /**
  464. * @todo
  465. */
  466. function _omega_tools_validate_theme_name($element, &$form_state) {
  467. system_rebuild_theme_data();
  468. if (!preg_match('/^[a-z][a-z0-9_]*$/', $element['#value'])) {
  469. form_error($element, t('The theme name is invalid. It may only contain lowercase numbers, letters and underscores and must start with a letter.'));
  470. }
  471. else if (_omega_tools_theme_exists($element['#value'])) {
  472. form_error($element, t('A theme with that name already exists. The machine-readable name must be unique.'));
  473. }
  474. }
  475. /**
  476. * @todo
  477. */
  478. function _omega_tools_validate_theme_settings($element, &$form_state) {
  479. $settings = drupal_parse_info_format($element['#value']);
  480. foreach ($settings as $key => $value) {
  481. if ($key !== 'settings') {
  482. form_error($element, t('You may only submit theme settings with this form.'));
  483. }
  484. }
  485. }
  486. /**
  487. * @todo
  488. */
  489. function _omega_tools_transform_theme_name($name) {
  490. $name = preg_replace('/^[^a-z]+/', '', strtolower($name));
  491. $name = preg_replace('/[^a-z0-9_]+/', '_', $name);
  492. $name = str_replace('__', '_', $name);
  493. $name = trim($name, '_');
  494. return $name;
  495. }
  496. /**
  497. * @todo
  498. */
  499. function _omega_tools_theme_access($theme) {
  500. if ($theme && user_access('administer themes')) {
  501. $themes = list_themes();
  502. if (!isset($themes[$theme->name]) || _omega_tools_is_editable($theme->name)) {
  503. return TRUE;
  504. }
  505. }
  506. return FALSE;
  507. }
  508. /**
  509. * @todo
  510. */
  511. function _omega_tools_is_starterkit($theme) {
  512. return array_key_exists($theme, omega_tools_starterkits());
  513. }
  514. /**
  515. * @todo
  516. */
  517. function _omega_tools_is_editable($theme) {
  518. $themes = list_themes();
  519. if (!in_array($theme, array('omega', 'alpha')) && strpos(drupal_get_path('theme', $theme), 'themes') !== 0) {
  520. if (isset($themes[$theme]->info['base theme'])) {
  521. $base = system_find_base_themes($themes, $theme);
  522. if (!empty($base) && isset($base['alpha']) && empty($themes[$theme]->info['locked'])) {
  523. return TRUE;
  524. }
  525. }
  526. }
  527. return FALSE;
  528. }