Skip to content

Commit fcd8a66

Browse files
committed
A new hope
1 parent 855687c commit fcd8a66

24 files changed

+1285
-741
lines changed

images/icon/icon-apps-active.png

249 Bytes
Loading

images/icon/icon-apps.png

372 Bytes
Loading

images/icon/icon-panopoly-active.png

1.65 KB
Loading

images/icon/icon-panopoly.png

1.46 KB
Loading

images/throbber.gif

2.37 KB
Loading

includes/config.batch.inc

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?php
2+
/**
3+
* @file
4+
* Kalatheme's subtheme config batch stuff
5+
*/

includes/config.form.inc

+344
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,344 @@
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

Comments
 (0)