|
| 1 | +<?php |
| 2 | +/** |
| 3 | + * @file |
| 4 | + * Kalatheme's subtheme config form stuff |
| 5 | + */ |
| 6 | + |
| 7 | +/** |
| 8 | + * Returns a list of Kalatheme base themes. |
| 9 | + */ |
| 10 | +function _kalatheme_get_base_themes() { |
| 11 | + $themes = list_themes(); |
| 12 | + |
| 13 | + $base_themes = array('kalatheme' => 'Kalatheme'); |
| 14 | + if (isset($themes['kalatheme']->sub_themes)) { |
| 15 | + $base_themes += $themes['kalatheme']->sub_themes; |
| 16 | + } |
| 17 | + |
| 18 | + return $base_themes; |
| 19 | +} |
| 20 | + |
| 21 | +/** |
| 22 | + * Form constructor for Bootstrap library selection form |
| 23 | + * |
| 24 | + * @return array |
| 25 | + */ |
| 26 | +function kalatheme_bootstrap_library_form() { |
| 27 | + $form = array(); |
| 28 | + |
| 29 | + $form['bootstrap'] = array( |
| 30 | + '#type' => 'fieldset', |
| 31 | + '#title' => t('Bootstrap Library'), |
| 32 | + '#weight' => -99, |
| 33 | + '#collapsible' => FALSE, |
| 34 | + '#collapsed' => FALSE, |
| 35 | + ); |
| 36 | + $form['bootstrap']['bootstrap_library'] = array( |
| 37 | + '#type' => 'select', |
| 38 | + '#title' => t('Select a Bootstrap library.'), |
| 39 | + '#description' => t('Select a Bootstrap library to use with your subtheme. Visit <a href="@bootswatch">Bootswatch</a> for more info. Select "custom" to upload a third party Bootstrap library such as one from <a href="@wrapbootstrap">Wrapbootstrap</a> or built using Bootstrap\'s <a href="@bootcustom">Customization Utility</a>.', array( |
| 40 | + '@bootswatch' => 'http://bootswatch.com/', |
| 41 | + '@wrapbootstrap' => 'http://wrapbootstrap.com/', |
| 42 | + '@bootcustom' => 'http://getbootstrap.com/customize/', |
| 43 | + )), |
| 44 | + '#ajax' => array( |
| 45 | + 'callback' => 'kalatheme_ajax_bootstrap_preview', |
| 46 | + 'wrapper' => 'kalapreview-image-load-image', |
| 47 | + 'method' => 'replace', |
| 48 | + 'effect' => 'fade', |
| 49 | + 'progress' => array('type' => 'none'), |
| 50 | + ), |
| 51 | + ); |
| 52 | + foreach (kalatheme_available_bootstrap_libraries() as $theme) { |
| 53 | + $form['bootstrap']['bootstrap_library']['#options'][$theme] = ucfirst($theme); |
| 54 | + } |
| 55 | + $form['bootstrap']['bootstrap_preview'] = array( |
| 56 | + '#type' => 'markup', |
| 57 | + '#prefix' => "<div id='kalapreview-image-load-image'>", |
| 58 | + '#suffix' => "</div>", |
| 59 | + ); |
| 60 | + $form['bootstrap']['bootstrap_upload'] = array( |
| 61 | + '#type' => 'file', |
| 62 | + '#title' => t('Custom Bootstrap library'), |
| 63 | + '#description' => t('Upload any <a href="@valid_doc">valid bootstrap library</a> here to complete your install. For example: %filename from your local computer. <strong>DISCLAIMER:</strong> This works pretty good with some libraries but not so great with others. Use this to kick start your project not as a end-all-be-all tool. ', array( |
| 64 | + '%filename' => 'name.tar.gz', |
| 65 | + '@valid_doc' => 'http://www.drupal.org/project/kalatheme', |
| 66 | + )), |
| 67 | + // This #states rule says that the "file upload" field should only |
| 68 | + // be shown if the "bootstrap_library" form element is set to "custom". |
| 69 | + '#states' => array( |
| 70 | + 'visible' => array( |
| 71 | + ':input[name="bootstrap_library"]' => array('value' => 'custom'), |
| 72 | + ), |
| 73 | + ) |
| 74 | + ); |
| 75 | + return $form; |
| 76 | +} |
| 77 | + |
| 78 | +/** |
| 79 | + * Form constructor for Bootstrap library selection form |
| 80 | + * |
| 81 | + * @return array |
| 82 | + */ |
| 83 | +function kalatheme_backend_check_form() { |
| 84 | + $form = array(); |
| 85 | + |
| 86 | + if (kalatheme_backend_check()) { |
| 87 | + $form['backend_check'] = array( |
| 88 | + '#weight' => -100, |
| 89 | + '#prefix' => '<div class="alert alert-success">', |
| 90 | + '#markup' => t("Your webserver is correctly configured to allow for custom Bootstrap libraries and subtheme generation!"), |
| 91 | + '#suffix' => '</div>', |
| 92 | + ); |
| 93 | + } |
| 94 | + else { |
| 95 | + $form['backend_check'] = array( |
| 96 | + '#weight' => -100, |
| 97 | + '#prefix' => '<div class="alert alert-danger">', |
| 98 | + '#markup' => t("If you want Kalatheme to be able to use custom Bootstrap libraries or generate subthemes automatically please properly configure your webserver."), |
| 99 | + // @todo add link to docs here |
| 100 | + '#suffix' => '</div>', |
| 101 | + ); |
| 102 | + } |
| 103 | + |
| 104 | + return $form; |
| 105 | +} |
| 106 | +/** |
| 107 | + * Handle custom Bootstrap library validation |
| 108 | + */ |
| 109 | +function kalatheme_custom_bootstrap_library_validate(&$form, &$form_state) { |
| 110 | + // Make sure the user has uploaded an archive |
| 111 | + // We handle validation of the archive in the submit handler |
| 112 | + if ($form_state['values']['bootstrap_library'] == 'custom') { |
| 113 | + if (empty($_FILES['files']['name']['bootstrap_upload'])) { |
| 114 | + form_set_error('bootstrap_upload', t('You must provide a custom Bootstrap library.')); |
| 115 | + } |
| 116 | + } |
| 117 | +} |
| 118 | + |
| 119 | +/** |
| 120 | + * Handle custom Bootstrap library submission |
| 121 | + */ |
| 122 | +function kalatheme_custom_bootstrap_library_submit(&$form, &$form_state) { |
| 123 | + // Save the uploaded file |
| 124 | + if ($_FILES['files']['name']['bootstrap_upload']) { |
| 125 | + // Summon the power of update manager |
| 126 | + module_load_include("inc", "update", "update.manager"); |
| 127 | + $validators = array('file_validate_extensions' => array(archiver_get_extensions())); |
| 128 | + $field = 'bootstrap_upload'; |
| 129 | + if (!($finfo = file_save_upload($field, $validators, NULL, FILE_EXISTS_REPLACE))) { |
| 130 | + // Failed to upload the file. file_save_upload() calls form_set_error() on |
| 131 | + // failure. |
| 132 | + return; |
| 133 | + } |
| 134 | + $local_cache = $finfo->uri; |
| 135 | + |
| 136 | + $project = 'kalatheme_bootstrap'; |
| 137 | + $directory = kalatheme_extract_directory('library') . '/' . $project; |
| 138 | + try { |
| 139 | + $archive = update_manager_archive_extract($local_cache, $directory); |
| 140 | + } |
| 141 | + catch (Exception $e) { |
| 142 | + form_set_error($field, $e->getMessage()); |
| 143 | + return; |
| 144 | + } |
| 145 | + |
| 146 | + $files = $archive->listContents(); |
| 147 | + if (!$files) { |
| 148 | + form_set_error($field, t('Provided archive contains no files.')); |
| 149 | + return; |
| 150 | + } |
| 151 | + foreach ($files as $file) { |
| 152 | + if (stripos($file, 'bootstrap.min.css') !== FALSE || stripos($file, 'bootstrap.css') !== FALSE) { |
| 153 | + $check_file = $file; |
| 154 | + break; |
| 155 | + } |
| 156 | + } |
| 157 | + if (!file_exists($directory . '/' . $check_file)) { |
| 158 | + form_set_error($field, t('Provided archive contains no files.')); |
| 159 | + return; |
| 160 | + } |
| 161 | + |
| 162 | + // Make sure the Updater registry is loaded. |
| 163 | + require_once dirname(__FILE__) . '/../kalatheme.updater.inc'; |
| 164 | + |
| 165 | + drupal_get_updaters(); |
| 166 | + try { |
| 167 | + $updater = Updater::factory($directory); |
| 168 | + } |
| 169 | + catch (Exception $e) { |
| 170 | + form_set_error($field, $e->getMessage()); |
| 171 | + return; |
| 172 | + } |
| 173 | + |
| 174 | + $project_real_location = drupal_realpath($directory); |
| 175 | + $arguments = array( |
| 176 | + 'project' => $project, |
| 177 | + 'updater_name' => get_class($updater), |
| 178 | + 'local_url' => $project_real_location, |
| 179 | + ); |
| 180 | + |
| 181 | + // If the owner of the directory we extracted is the same as the |
| 182 | + // owner of our configuration directory (e.g. sites/default) where we're |
| 183 | + // trying to install the code, there's no need to prompt for FTP/SSH |
| 184 | + // credentials. Instead, we instantiate a FileTransferLocal and invoke |
| 185 | + // update_authorize_run_install() directly. |
| 186 | + if (kalatheme_has_write_access()) { |
| 187 | + $filetransfer = new FileTransferLocal(DRUPAL_ROOT); |
| 188 | + call_user_func_array('kalatheme_run_install', array_merge(array($filetransfer), $arguments)); |
| 189 | + } |
| 190 | + // Otherwise, go through the regular workflow to prompt for FTP/SSH |
| 191 | + // credentials and invoke update_authorize_run_install() indirectly with |
| 192 | + // whatever FileTransfer object authorize.php creates for us. |
| 193 | + else { |
| 194 | + system_authorized_init('kalatheme_run_install', drupal_get_path('module', 'update') . '/update.authorize.inc', $arguments, t('Update manager')); |
| 195 | + $form_state['redirect'] = system_authorized_get_url(); |
| 196 | + } |
| 197 | + } |
| 198 | +} |
| 199 | + |
| 200 | + |
| 201 | +/** |
| 202 | + * The batch builder and processor for moving files to drupal |
| 203 | + * |
| 204 | + * taken from update_authorize_run_update |
| 205 | + * builds a batch and process it for installing modules from the templocation |
| 206 | + */ |
| 207 | +function kalatheme_run_install($filetransfer, $project, $updater_name, $local_url) { |
| 208 | + $operations[] = array( |
| 209 | + 'kalatheme_authorize_batch_copy_project', |
| 210 | + array( |
| 211 | + $project, |
| 212 | + $updater_name, |
| 213 | + $local_url, |
| 214 | + $filetransfer, |
| 215 | + ), |
| 216 | + ); |
| 217 | + |
| 218 | + // @todo Instantiate our Updater to set the human-readable title? |
| 219 | + $batch = array( |
| 220 | + 'title' => t('Installing %project', array('%project' => $project)), |
| 221 | + 'init_message' => t('Preparing to install'), |
| 222 | + 'operations' => $operations, |
| 223 | + // @todo Use a different finished callback for different messages? |
| 224 | + 'finished' => 'update_authorize_install_batch_finished', |
| 225 | + 'file' => drupal_get_path('theme', 'kalatheme') . '/kalatheme.authorize.inc', |
| 226 | + ); |
| 227 | + batch_set($batch); |
| 228 | + |
| 229 | + // Invoke the batch via authorize.php. |
| 230 | + //system_authorized_batch_process(); |
| 231 | +} |
| 232 | + |
| 233 | +/** |
| 234 | + * List of all themes available from bootswatch; only scalar values can be |
| 235 | + * constants. |
| 236 | + * |
| 237 | + * @return array |
| 238 | + */ |
| 239 | +function kalatheme_available_bootstrap_libraries() { |
| 240 | + $libs = array( |
| 241 | + 'default', |
| 242 | + 'amelia', |
| 243 | + 'cerulean', |
| 244 | + 'cosmo', |
| 245 | + 'cyborg', |
| 246 | + 'flatly', |
| 247 | + 'journal', |
| 248 | + 'lumen', |
| 249 | + 'readable', |
| 250 | + 'simplex', |
| 251 | + 'slate', |
| 252 | + 'spacelab', |
| 253 | + 'superhero', |
| 254 | + 'united', |
| 255 | + 'yeti', |
| 256 | + 'none' |
| 257 | + ); |
| 258 | + if (kalatheme_backend_check()){ |
| 259 | + array_push($libs, 'custom'); |
| 260 | + } |
| 261 | + return $libs; |
| 262 | +} |
| 263 | + |
| 264 | +/** |
| 265 | + * Ajax callback that returns HTML to the setup form so that the user |
| 266 | + * can see a preview of the bootstrap library they are selecting. |
| 267 | + * |
| 268 | + * @param $form |
| 269 | + * Form |
| 270 | + * @param $form_state |
| 271 | + * Form state |
| 272 | + * |
| 273 | + * @return |
| 274 | + * Updated form state to be merged back in |
| 275 | + * |
| 276 | + */ |
| 277 | +function kalatheme_ajax_bootstrap_preview($form, &$form_state) { |
| 278 | + $theme = $form_state['values']['bootstrap_library']; |
| 279 | + if ($theme == 'default' || $theme == 'custom' || $theme == 'none') { |
| 280 | + $form['bootstrap']['bootstrap_preview']['#markup'] = t(''); |
| 281 | + } |
| 282 | + else { |
| 283 | + // @todo: Do this in a way that doesn't suck and maybe incorporate some |
| 284 | + // styles as seen on bootswatch? |
| 285 | + $form['bootstrap']['bootstrap_preview']['#markup'] = t('<img src="@preview">', array('@preview' => 'http://bootswatch.com/' . $theme . '/thumbnail.png')); |
| 286 | + } |
| 287 | + return $form['bootstrap']['bootstrap_preview']; |
| 288 | +} |
| 289 | + |
| 290 | +/** |
| 291 | + * We want to check if the webserver can write our stuff to the right places. |
| 292 | + * If it can't then we are going to tell the user what's up. |
| 293 | + * |
| 294 | + * @return |
| 295 | + * True if all good, message if no good |
| 296 | + */ |
| 297 | +function kalatheme_backend_check() { |
| 298 | + // Verify FTP support |
| 299 | + $ftp_installed = extension_loaded('ftp'); |
| 300 | + // Verify SSH support |
| 301 | + $ssh_installed = extension_loaded('ssh2'); |
| 302 | + // Verify web server write permissions |
| 303 | + $install_permissions = kalatheme_has_write_access(); |
| 304 | + // Verify update module is enabled |
| 305 | + $updates_module = module_exists('update'); |
| 306 | + |
| 307 | + return (($ftp_installed || $ssh_installed || $install_permissions) && $updates_module); |
| 308 | +} |
| 309 | + |
| 310 | +/** |
| 311 | + * Check whether Kalatheme has write access to libraries and modules directories. |
| 312 | + * |
| 313 | + * @return boolean |
| 314 | + */ |
| 315 | +function kalatheme_has_write_access() { |
| 316 | + return is_writable(drupal_realpath(kalatheme_lib_dir())) && is_writable(drupal_realpath('sites/all/modules')); |
| 317 | +} |
| 318 | + |
| 319 | +/** |
| 320 | + * Return the libraries dir to check |
| 321 | + */ |
| 322 | +function kalatheme_lib_dir() { |
| 323 | + if (!is_dir('sites/all/libraries')) { |
| 324 | + mkdir(DRUPAL_ROOT . '/sites/all/libraries'); |
| 325 | + } |
| 326 | + return is_dir('sites/all/libraries') ? 'sites/all/libraries' : 'sites/all'; |
| 327 | +} |
| 328 | + |
| 329 | +/** |
| 330 | + * Wrapper for _update_manager_extract_directory() |
| 331 | + * |
| 332 | + * Since libraries and themes can live in the same location, we need to |
| 333 | + * namespace the types so they don't collide like the colorbox module. |
| 334 | + */ |
| 335 | +function kalatheme_extract_directory($type = '') { |
| 336 | + $directory = _update_manager_extract_directory(); |
| 337 | + if ($type) { |
| 338 | + $directory .= '/' . $type; |
| 339 | + if (!file_exists($directory)) { |
| 340 | + mkdir($directory); |
| 341 | + } |
| 342 | + } |
| 343 | + return $directory; |
| 344 | +} |
0 commit comments