You are here

live_css.module in Live CSS 6.2

File

live_css.module
View source
<?php

/**
 * Implements hook_menu().
 */
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;
}

/**
 * Implements hook_perm().
 */
function live_css_perm() {
  return array(
    'edit css',
  );
}

/**
 * Implements hook_settings()
 */
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;
}

/* get the directory listing for the theme files of ace */
function live_css_list_files($folder) {
  $results = array();
  $handler = opendir($folder);
  while ($file = readdir($handler)) {
    if ($file != '.' && $file != '..') {
      $results[] = $file;
    }
  }
  closedir($handler);
  return $results;
}

/**
 * Implements hook_init().
 */
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');
  }

  //check permissions
  if (user_access('edit css')) {

    //set settings
    $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'];

  // The URL may contain cache data. In that case, we need to strip them.
  // i.e. http://.../css/my_file.css?m1unhm
  $sanitized_url = _live_css_sanitize_css_url($href);

  // File path relative to Drupal installation folder.
  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;
  }

  // Save file back.
  $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,
  ));
}

/**
 * Helper function to sanitize a URL.
 * Removes cache information from url of CSS files.
 */
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;
}

/**
 * Helper function to get the document root for the current Drupal installation.
 * $_SERVER['DOCUMENT_ROOT'] is not reliable across all systems, so we need a
 * way to get the correct value.
 */
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)));
}

Functions

Namesort descending Description
live_css_admin Implements hook_settings()
live_css_init Implements hook_init().
live_css_list_files
live_css_list_themes
live_css_menu Implements hook_menu().
live_css_perm Implements hook_perm().
live_css_save
_live_css_document_root Helper function to get the document root for the current Drupal installation. $_SERVER['DOCUMENT_ROOT'] is not reliable across all systems, so we need a way to get the correct value.
_live_css_sanitize_css_url Helper function to sanitize a URL. Removes cache information from url of CSS files.