View source
<?php
function live_css_menu() {
$items = array();
$items['css/save'] = array(
'page callback' => 'live_css_save',
'access arguments' => array(
'edit css',
),
'type' => MENU_CALLBACK,
);
$items['admin/settings/live_css'] = array(
'title' => t('Live CSS'),
'page callback' => 'drupal_get_form',
'page arguments' => array(
'live_css_admin',
),
'access arguments' => array(
'access administration pages',
),
'type' => MENU_NORMAL_ITEM,
);
return $items;
}
function live_css_perm() {
return array(
'edit css',
);
}
function live_css_admin() {
$form = array();
$form['live_css_less'] = array(
'#type' => 'checkbox',
'#title' => t('Enable LESS Support'),
'#default_value' => variable_get('live_css_less', 1),
'#description' => t('Allows the live editing and display of LESS files on the site, by simply embedding stylesheets with a "less" extension instead of "css". The Less is parsed on each page load, even for anonymous users. In production you may wish to disable this feature and use the LESS module instead.'),
);
$form['live_css_hideadmin'] = array(
'#type' => 'checkbox',
'#title' => t('Hide Admin Menu'),
'#default_value' => variable_get('live_css_hideadmin', 1),
'#description' => t('Automatically hides the administration menu when editing CSS.'),
);
$form['live_css_hidemodules'] = array(
'#type' => 'checkbox',
'#title' => t('Only show theme CSS'),
'#default_value' => variable_get('live_css_hidemodules', 0),
'#description' => t('Removes module and other styles from the CSS list.'),
);
$form['live_css_theme'] = array(
'#type' => 'select',
'#title' => t('Editor Theme'),
'#default_value' => variable_get('live_css_theme', 'twilight'),
'#options' => live_css_list_themes(),
);
$form['live_css_fontsize'] = array(
'#type' => 'select',
'#title' => t('Font Size'),
'#default_value' => variable_get('live_css_fontsize', '12px'),
'#options' => array(
'8px' => '8px',
'10px' => '10px',
'11px' => '11px',
'12px' => '12px',
'14px' => '14px',
'16px' => '16px',
'18px' => '18px',
),
);
$form['live_css_tabsize'] = array(
'#type' => 'select',
'#title' => t('Tab Size'),
'#default_value' => variable_get('live_css_tabsize', 2),
'#options' => array(
1 => '1',
2 => '2',
3 => '3',
4 => '4',
),
);
$form['live_css_softtabs'] = array(
'#type' => 'checkbox',
'#title' => t('Soft Tabs'),
'#default_value' => variable_get('live_css_softtabs', 1),
);
return system_settings_form($form);
}
function live_css_list_themes() {
$result = array();
$files = live_css_list_files(dirname(__FILE__) . '/ace/src');
foreach ($files as $file) {
if (substr($file, 0, 5) == 'theme') {
$theme = substr($file, 6, strlen($file) - 9);
$name = ucwords(str_replace('_', ' ', $theme));
$result[$theme] = $name;
}
}
return $result;
}
function live_css_list_files($folder) {
$results = array();
$handler = opendir($folder);
while ($file = readdir($handler)) {
if ($file != '.' && $file != '..') {
$results[] = $file;
}
}
closedir($handler);
return $results;
}
function live_css_init() {
$less = variable_get('live_css_less', 1);
if ($less) {
drupal_add_js(drupal_get_path('module', 'live_css') . '/less-display.js');
drupal_add_js(drupal_get_path('module', 'live_css') . '/less-1.1.3.min.js');
}
if (user_access('edit css')) {
$theme = variable_get('live_css_theme', 'twilight');
$settings = array();
$settings['theme'] = $theme;
$settings['autoload'] = false;
$settings['hideadmin'] = variable_get('live_css_hideadmin', 1);
$settings['hidemodules'] = variable_get('live_css_hidemodules', 0);
$settings['fontsize'] = variable_get('live_css_fontsize', '12px');
$settings['tabsize'] = (int) variable_get('live_css_tabsize', 2);
$settings['softtabs'] = (bool) variable_get('live_css_softtabs', 1);
$settings['less'] = $less;
$settings['savepath'] = url('css/save');
drupal_add_js(array(
'live_css' => $settings,
), 'setting');
drupal_add_js(drupal_get_path('module', 'live_css') . '/less-1.1.3.min.js');
drupal_add_js(drupal_get_path('module', 'live_css') . '/ace/src/ace.js');
drupal_add_js(drupal_get_path('module', 'live_css') . '/ace/src/mode-css.js');
drupal_add_js(drupal_get_path('module', 'live_css') . '/ace/src/theme-' . $theme . '.js');
drupal_add_js(drupal_get_path('module', 'live_css') . '/plugins.js');
drupal_add_css(drupal_get_path('module', 'live_css') . '/css.css', 'module', 'all', FALSE);
drupal_add_js(drupal_get_path('module', 'live_css') . '/css.js');
}
}
function live_css_save() {
if (!user_access('edit css')) {
return;
}
$css = $_POST['css'];
$href = $_POST['href'];
$sanitized_url = _live_css_sanitize_css_url($href);
global $base_url;
$stripped_url = drupal_substr($sanitized_url, drupal_strlen($base_url), drupal_strlen($sanitized_url));
$relative_file_path = _live_css_document_root() . $stripped_url;
if (substr($relative_file_path, -4) != '.css' && substr($relative_file_path, -5) != '.less') {
echo json_encode(array(
'result' => 'failure',
'filename' => $href,
'msg' => 'Can\'t save to files without a \'less\' or \'css\' extension!',
));
return;
}
if (file_munge_filename($relative_file_path, 'css less') != $relative_file_path) {
echo json_encode(array(
'result' => 'failure',
'filename' => $href,
'msg' => 'The url used contains a sub-filextension which poses a security threat. Saving not allowed.',
));
return;
}
$msg = '';
$fh = fopen($relative_file_path, 'w');
if ($fh !== FALSE) {
fwrite($fh, $css);
fclose($fh);
$result = 'success';
}
else {
$result = 'failure';
$msg = 'Can\'t open file ' . $relative_file_path . ' from ' . $href . '. Ensure that you have full write access and that the path is correct.';
}
echo json_encode(array(
'result' => $result,
'filename' => $href,
'msg' => $msg,
));
}
function _live_css_sanitize_css_url($url) {
$result = $url;
$pos = strpos($url, '.css?');
if ($pos !== FALSE) {
$result = substr($url, 0, $pos + 4);
}
$pos = strpos($url, '.less?');
if ($pos !== FALSE) {
$result = substr($url, 0, $pos + 5);
}
return $result;
}
function _live_css_document_root() {
$absolute_dir = dirname(__FILE__);
$relative_dir = drupal_get_path('module', 'live_css');
return drupal_substr($absolute_dir, 0, -1 * (1 + drupal_strlen($relative_dir)));
}