security update core+modules
This commit is contained in:
137
sites/all/modules/less/includes/less.admin.inc
Normal file
137
sites/all/modules/less/includes/less.admin.inc
Normal file
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains the administration pages for LESS.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Form for LESS module settings.
|
||||
*/
|
||||
function less_settings_form($form, &$form_state) {
|
||||
|
||||
$form['less_flush'] = array(
|
||||
'#type' => 'fieldset',
|
||||
'#collapsible' => FALSE,
|
||||
'#value' => t('Click this button to flag all LESS files for regeneration.'),
|
||||
);
|
||||
|
||||
$form['less_flush']['flush'] = array(
|
||||
'#type' => 'submit',
|
||||
'#submit' => array('_flush_less'),
|
||||
'#value' => t('Flush LESS files'),
|
||||
);
|
||||
|
||||
$registered_engines = _less_get_engines();
|
||||
|
||||
$less_engines = array();
|
||||
|
||||
foreach ($registered_engines as $library => $engine) {
|
||||
|
||||
$less_engines[] = libraries_detect($library);
|
||||
}
|
||||
|
||||
$less_engine_element = array(
|
||||
'#type' => 'radios',
|
||||
'#title' => t('LESS engine'),
|
||||
'#options' => array(),
|
||||
'#required' => TRUE,
|
||||
'#default_value' => variable_get('less_engine', 'lessphp'),
|
||||
);
|
||||
|
||||
foreach ($less_engines as $less_engine) {
|
||||
|
||||
$less_engine_element['#options'][$less_engine['machine name']] = $less_engine['name'];
|
||||
|
||||
$less_engine_element[$less_engine['machine name']] = array(
|
||||
'#type' => 'radio',
|
||||
'#title' => t('@engine_name - <a href="@vendor_url">@vendor_url</a>', array('@engine_name' => $less_engine['name'], '@vendor_url' => $less_engine['vendor url'])),
|
||||
'#return_value' => $less_engine['machine name'],
|
||||
'#description' => t('Missing - Click vendor link above to read installation instructions.'),
|
||||
'#disabled' => empty($less_engine['installed']),
|
||||
);
|
||||
|
||||
if ($less_engine['installed']) {
|
||||
$less_engine_element[$less_engine['machine name']]['#description'] = t('v%version Installed', array('%version' => $less_engine['version']));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$form['less_engine'] = $less_engine_element;
|
||||
|
||||
|
||||
$lessautoprefixer_library = libraries_detect('lessautoprefixer');
|
||||
|
||||
$form[LESS_AUTOPREFIXER] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Use @name - <a href="@vendor_url">@vendor_url</a>', array('@name' => $lessautoprefixer_library['name'], '@vendor_url' => $lessautoprefixer_library['vendor url'])),
|
||||
'#description' => t('Enable automatic prefixing of vendor CSS extensions.'),
|
||||
'#default_value' => variable_get(LESS_AUTOPREFIXER, FALSE),
|
||||
'#disabled' => empty($lessautoprefixer_library['installed']),
|
||||
);
|
||||
|
||||
if ($lessautoprefixer_library['installed']) {
|
||||
$form[LESS_AUTOPREFIXER]['#description'] .= '<br />'. t('v%version Installed', array('%version' => $lessautoprefixer_library['version']));
|
||||
}
|
||||
|
||||
$form['developer_options'] = array(
|
||||
'#type' => 'fieldset',
|
||||
'#title' => t('Developer Options'),
|
||||
'#collapsible' => TRUE,
|
||||
'#collapsed' => !(variable_get(LESS_DEVEL, FALSE)),
|
||||
);
|
||||
|
||||
$form['developer_options'][LESS_DEVEL] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Developer Mode'),
|
||||
'#description' => t('Enable developer mode to ensure LESS files are regenerated every page load.'),
|
||||
'#default_value' => variable_get(LESS_DEVEL, FALSE),
|
||||
);
|
||||
|
||||
$form['developer_options'][LESS_SOURCE_MAPS] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Source Maps'),
|
||||
'#description' => t('Enable source maps output while "Developer Mode" is enabled.'),
|
||||
'#default_value' => variable_get(LESS_SOURCE_MAPS, FALSE),
|
||||
'#states' => array(
|
||||
'enabled' => array(
|
||||
':input[name="' . LESS_DEVEL . '"]' => array('checked' => TRUE),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
$form['developer_options'][LESS_WATCH] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Watch Mode'),
|
||||
'#description' => t('Enable watch mode while developer mode is active to automatically reload styles when changes are detected, including changes to @import-ed files. Does not cause a page reload.'),
|
||||
'#default_value' => variable_get(LESS_WATCH, FALSE),
|
||||
'#states' => array(
|
||||
'enabled' => array(
|
||||
':input[name="' . LESS_DEVEL . '"]' => array('checked' => TRUE),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
$form['#submit'] = array('less_settings_form_submit');
|
||||
|
||||
return system_settings_form($form);
|
||||
}
|
||||
|
||||
/**
|
||||
* Form submission function.
|
||||
*
|
||||
* Trigger clear of LESS module cache data.
|
||||
*/
|
||||
function less_settings_form_submit($form, &$form_state) {
|
||||
cache_clear_all('less:', 'cache', TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit handler for cache clear button.
|
||||
*/
|
||||
function _flush_less($form, &$form_state) {
|
||||
|
||||
less_flush_caches();
|
||||
|
||||
drupal_set_message(t('LESS files cache cleared.'), 'status');
|
||||
}
|
209
sites/all/modules/less/includes/less.libraries.inc
Normal file
209
sites/all/modules/less/includes/less.libraries.inc
Normal file
@@ -0,0 +1,209 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains Libraries API integration.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_libraries_info().
|
||||
*/
|
||||
function less_libraries_info() {
|
||||
$libraries = array();
|
||||
|
||||
/**
|
||||
* Legacy leafo/lessphp library.
|
||||
*/
|
||||
$libraries['lessphp'] = array(
|
||||
'name' => 'lessphp (Not recommended)',
|
||||
'vendor url' => 'http://leafo.net/lessphp/',
|
||||
'download url' => 'http://leafo.net/lessphp/',
|
||||
'version arguments' => array(
|
||||
'file' => 'lessc.inc.php',
|
||||
'pattern' => '/VERSION\s*=\s*["\']v?([\d\.]+)/',
|
||||
'lines' => 50,
|
||||
),
|
||||
'files' => array(
|
||||
'php' => array(
|
||||
'lessc.inc.php',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
_less_lessphp_locate($libraries['lessphp']);
|
||||
|
||||
/**
|
||||
* Newer oyejorge/less.php library. Closer to canonical spec from lesscss.org.
|
||||
*/
|
||||
$libraries['less.php'] = array(
|
||||
'name' => 'less.php',
|
||||
'vendor url' => 'http://lessphp.gpeasy.com/',
|
||||
'download url' => 'http://lessphp.gpeasy.com/#integration-with-other-projects',
|
||||
'version arguments' => array(
|
||||
'file' => 'Version.php',
|
||||
'pattern' => '/version\s*=\s*["\']([\d\.]+)/',
|
||||
'lines' => 20,
|
||||
),
|
||||
'files' => array(
|
||||
'php' => array(
|
||||
'Less.php',
|
||||
),
|
||||
),
|
||||
'versions' => array(
|
||||
'1.7.0' => array(),
|
||||
),
|
||||
);
|
||||
|
||||
_less_less_php_locate($libraries['less.php']);
|
||||
|
||||
/**
|
||||
* Canonical version of LESS language.
|
||||
*/
|
||||
$libraries['less.js'] = array(
|
||||
'name' => 'less.js',
|
||||
'vendor url' => 'http://lesscss.org/',
|
||||
'download url' => 'http://lesscss.org/usage/#using-less-environments',
|
||||
'library path' => drupal_get_path('module', 'less') . '/classes',
|
||||
'version callback' => array('Lessjs', 'version'),
|
||||
/**
|
||||
* Integer indexed 'version arguments' array causes 'version callback' to be
|
||||
* run through call_user_func_array().
|
||||
*
|
||||
* @see call_user_func_array()
|
||||
*/
|
||||
'version arguments' => array(
|
||||
0 => 'not used',
|
||||
),
|
||||
'files' => array(
|
||||
'php' => array(
|
||||
'class.lessjs.inc',
|
||||
),
|
||||
),
|
||||
'versions' => array(
|
||||
'1.5.0' => array(),
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* Autoprefixer
|
||||
*/
|
||||
$libraries['lessautoprefixer'] = array(
|
||||
'name' => 'Autoprefixer',
|
||||
'vendor url' => 'https://github.com/ai/autoprefixer',
|
||||
'download url' => 'https://github.com/ai/autoprefixer/releases',
|
||||
'library path' => drupal_get_path('module', 'less') . '/classes',
|
||||
'version callback' => array('LessAutoprefixer', 'version'),
|
||||
/**
|
||||
* Integer indexed 'version arguments' array causes 'version callback' to be
|
||||
* run through call_user_func_array().
|
||||
*
|
||||
* @see call_user_func_array()
|
||||
*/
|
||||
'version arguments' => array(
|
||||
0 => 'not used',
|
||||
),
|
||||
'files' => array(
|
||||
'php' => array(
|
||||
'class.lessautoprefixer.inc',
|
||||
),
|
||||
),
|
||||
'versions' => array(
|
||||
'1.1' => array(),
|
||||
),
|
||||
);
|
||||
|
||||
return $libraries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Locates oyejorge/less.php in the many possible places it could be.
|
||||
*
|
||||
* @param array $library
|
||||
* Libraries definition array.
|
||||
*/
|
||||
function _less_less_php_locate(&$library) {
|
||||
|
||||
$locations = array();
|
||||
|
||||
// Primary libraries location
|
||||
$locations[] = libraries_get_path('less.php');
|
||||
|
||||
// lessphp drop-in replacement location
|
||||
$locations[] = libraries_get_path('lessphp');
|
||||
|
||||
// Composer location
|
||||
$locations[] = drupal_get_path('module', 'less') . '/vendor/oyejorge/less.php';
|
||||
|
||||
$version_files = array(
|
||||
'lib/Less/Version.php' => 'lessc.inc.php', // Source code
|
||||
'Version.php' => 'Less.php', // Compiled
|
||||
);
|
||||
|
||||
_less_libraries_determine_location($library, $locations, $version_files);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Locates leafo/lessphp in the many possible places it could be.
|
||||
*
|
||||
* @param array $library
|
||||
* Libraries definition array.
|
||||
*/
|
||||
function _less_lessphp_locate(&$library) {
|
||||
|
||||
$locations = array();
|
||||
|
||||
// Primary libraries location
|
||||
$locations[] = libraries_get_path('lessphp');
|
||||
|
||||
// Legacy bundled location
|
||||
$locations[] = drupal_get_path('module', 'less') . '/lessphp';
|
||||
|
||||
// Composer location
|
||||
$locations[] = drupal_get_path('module', 'less') . '/vendor/leafo/lessphp';
|
||||
|
||||
/*
|
||||
* oyejorge/less.php does not have the actual version number in lessc.inc.php,
|
||||
* so we don't have to worry about mistaken identity.
|
||||
*/
|
||||
$version_files = array(
|
||||
'lessc.inc.php' => 'lessc.inc.php',
|
||||
);
|
||||
|
||||
_less_libraries_determine_location($library, $locations, $version_files);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that checks locations for LESS libraries.
|
||||
*
|
||||
* @param array &$library
|
||||
* Library in question. Paths to found libraries will be added here.
|
||||
* @param array $locations
|
||||
* Array of paths of potential library installs relative to DRUPAL_ROOT.
|
||||
* @param array $version_files
|
||||
* Array of key => value pairs, where key is location library version number,
|
||||
* and value is the location of that file that to be included when this
|
||||
* library is loaded with libraries_load().
|
||||
*/
|
||||
function _less_libraries_determine_location(array &$library, array $locations, array $version_files) {
|
||||
|
||||
foreach (array_filter($locations) as $location) {
|
||||
|
||||
foreach ($version_files as $version_file => $class_file) {
|
||||
|
||||
if (file_exists($location . DIRECTORY_SEPARATOR . $version_file)) {
|
||||
|
||||
$library['library path'] = $location;
|
||||
$library['files'] = array(
|
||||
'php' => array(
|
||||
$class_file,
|
||||
),
|
||||
);
|
||||
|
||||
$library['version arguments']['file'] = $version_file;
|
||||
|
||||
return; // File has been found, skip remaining $locations and $version_files
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
281
sites/all/modules/less/includes/less.process.inc
Normal file
281
sites/all/modules/less/includes/less.process.inc
Normal file
@@ -0,0 +1,281 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains functions related to compiling .less files.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Attach LESS settings to each file as appropriate.
|
||||
*
|
||||
* @param array[] $item
|
||||
* @param string $key
|
||||
*/
|
||||
function _less_attach_settings(&$item, $key) {
|
||||
|
||||
$defaults = array(
|
||||
'less' => less_get_settings(), // Bare defaults for LESS.
|
||||
);
|
||||
|
||||
// These items must be reset for consistent operation.
|
||||
$nullify = array(
|
||||
'less' => array(
|
||||
'output_file' => NULL,
|
||||
'build_required' => NULL,
|
||||
),
|
||||
);
|
||||
|
||||
// Merge in any info from $item.
|
||||
$item = array_replace_recursive($defaults, $item, $nullify);
|
||||
|
||||
$item['less']['input_file'] = $item['data'];
|
||||
|
||||
$less_settings = less_get_settings(_less_file_owner($item['less']['input_file']));
|
||||
|
||||
// array_replace_recursive() works on keys, flip to not use numeric keys.
|
||||
$less_settings['paths'] = array_flip($less_settings['paths']);
|
||||
$item['less']['paths'] = array_flip($item['less']['paths']);
|
||||
|
||||
// Merge defaults with any per file settings.
|
||||
$item['less'] = array_replace_recursive($less_settings, $item['less']);
|
||||
|
||||
// First array_flips before merge removed duplicates, so just flip back.
|
||||
$item['less']['paths'] = array_flip($item['less']['paths']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine output filename and add it to the settings array.
|
||||
*
|
||||
* @param array[] $item
|
||||
* @param string $key
|
||||
*/
|
||||
function _less_output_path(&$item, $key) {
|
||||
|
||||
$input_file = $item['less']['input_file'];
|
||||
|
||||
$less_settings = $item['less'];
|
||||
|
||||
// array_multisort() the data so that the hash returns the same hash regardless order of data.
|
||||
array_multisort($less_settings);
|
||||
|
||||
$output_path_array = array(
|
||||
'!less_output_dir' => LESS_DIRECTORY,
|
||||
// Strip '.css' extension of filenames following the RTL extension pattern.
|
||||
'!input_file_basename' => basename(basename($input_file, '.less'), '.css'),
|
||||
// drupal_json_encode() is used because serialize() throws an error with lambda functions.
|
||||
'!settings_hash' => drupal_hash_base64(drupal_json_encode($less_settings)),
|
||||
);
|
||||
|
||||
$output_path = format_string('!less_output_dir/!input_file_basename.!settings_hash.css', $output_path_array);
|
||||
|
||||
$item['less']['output_file'] = $output_path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the file needs to be rebuilt based on changes to @import'ed files.
|
||||
*
|
||||
* @param array[] $item
|
||||
* @param string $key
|
||||
*/
|
||||
function _less_check_build(&$item, $key) {
|
||||
|
||||
$input_file = $item['less']['input_file'];
|
||||
|
||||
$build_required = FALSE;
|
||||
|
||||
// Set $rebuild if this file or its children have been modified.
|
||||
if ($less_file_cache = cache_get('less:devel:' . drupal_hash_base64($input_file))) {
|
||||
|
||||
// Iterate over each file and check if there are any changes.
|
||||
foreach ($less_file_cache->data as $filepath => $filemtime) {
|
||||
|
||||
// Only rebuild if there has been a change to a file.
|
||||
if (is_file($filepath) && filemtime($filepath) > $filemtime) {
|
||||
$build_required = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
// No cache data, force a rebuild for later comparison.
|
||||
$build_required = TRUE;
|
||||
}
|
||||
|
||||
$item['less']['build_required'] = $build_required;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a .less file and save the compiled styles.
|
||||
*
|
||||
* @param array[] $item
|
||||
* @param string $key
|
||||
*
|
||||
* @see \LessEngineInterface
|
||||
*/
|
||||
function _less_process_file(&$item, $key) {
|
||||
|
||||
$less_settings = $item['less'];
|
||||
|
||||
// $output_file doesn't exist or is flagged for build.
|
||||
if (!is_file($item['less']['output_file']) || !empty($item['less']['build_required'])) {
|
||||
|
||||
$output_data = NULL;
|
||||
|
||||
try {
|
||||
|
||||
$engine = less_get_engine($less_settings['input_file']);
|
||||
|
||||
$engine->setImportDirectories($less_settings['paths']);
|
||||
|
||||
if ($less_settings[LESS_DEVEL]) {
|
||||
|
||||
$engine->setSourceMaps($less_settings[LESS_SOURCE_MAPS], DRUPAL_ROOT, base_path());
|
||||
}
|
||||
|
||||
$engine->modifyVariables($less_settings['variables']);
|
||||
|
||||
$output_data = $engine->compile();
|
||||
|
||||
if ($less_settings[LESS_DEVEL]) {
|
||||
|
||||
_less_cache_dependencies($less_settings['input_file'], $engine->getDependencies());
|
||||
}
|
||||
}
|
||||
catch (Exception $e) {
|
||||
|
||||
$message_vars = array(
|
||||
'@message' => $e->getMessage(),
|
||||
'%input_file' => $item['less']['input_file'],
|
||||
);
|
||||
|
||||
watchdog('LESS', 'LESS error: @message, %input_file', $message_vars, WATCHDOG_ERROR);
|
||||
|
||||
if (user_access(LESS_PERMISSION)) {
|
||||
drupal_set_message(t('LESS error: @message, %input_file', $message_vars), 'error');
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($output_data)) {
|
||||
|
||||
// Fix paths for images as .css is in different location.
|
||||
$output_data = _less_rewrite_paths($item['less']['input_file'], $output_data);
|
||||
|
||||
// Ensure the destination directory exists.
|
||||
if (_less_ensure_directory(dirname($item['less']['output_file']))) {
|
||||
|
||||
file_unmanaged_save_data($output_data, $item['less']['output_file'], FILE_EXISTS_REPLACE);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_file($item['less']['output_file']) && $item['less'][LESS_AUTOPREFIXER]) {
|
||||
|
||||
if (($lessautoprefixer_library = libraries_load('lessautoprefixer')) && $lessautoprefixer_library['installed']) {
|
||||
|
||||
try {
|
||||
|
||||
LessAutoprefixer::create(drupal_realpath($item['less']['output_file']))->compile();
|
||||
}
|
||||
catch (Exception $e) {
|
||||
|
||||
$message_vars = array(
|
||||
'@message' => $e->getMessage(),
|
||||
'%input_file' => $item['less']['output_file'],
|
||||
);
|
||||
|
||||
watchdog('LESS', 'Autoprefixer error: @message, %input_file', $message_vars, WATCHDOG_ERROR);
|
||||
|
||||
if (user_access(LESS_PERMISSION)) {
|
||||
drupal_set_message(t('Autoprefixer error: @message, %input_file', $message_vars), 'error');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_file($item['less']['output_file'])) {
|
||||
|
||||
// Set render path of the stylesheet to the compiled output.
|
||||
$item['data'] = $item['less']['output_file'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array[] $item
|
||||
* @param string $key
|
||||
*/
|
||||
function _less_store_cache_info(&$item, $key) {
|
||||
|
||||
// Only match when output_file exists.
|
||||
if ($item['data'] === $item['less']['output_file']) {
|
||||
|
||||
$less_watch_cache = $item;
|
||||
|
||||
$less_watch_cache['data'] = $item['less']['input_file'];
|
||||
|
||||
cache_set('less:watch:' . drupal_hash_base64(file_create_url($item['less']['output_file'])), $less_watch_cache);
|
||||
|
||||
// 'preprocess' being FALSE generates a discreet <link /> rather than an @import.
|
||||
$item['preprocess'] = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize keeping track of changed files.
|
||||
*
|
||||
* @param string $input_file
|
||||
* Path of source file.
|
||||
* @param string[] $dependencies
|
||||
* Array of files that are @import'ed in $input_file, recursively.
|
||||
*/
|
||||
function _less_cache_dependencies($input_file, $dependencies = array()) {
|
||||
|
||||
// Add $input_file to $dependencies as it is not in return from some engines.
|
||||
$dependencies = array_merge(array($input_file), (array) $dependencies);
|
||||
|
||||
$watched_files = array();
|
||||
|
||||
foreach ($dependencies as $dependency) {
|
||||
|
||||
// Full path on file should enforce uniqueness in associative array.
|
||||
$watched_files[drupal_realpath($dependency)] = filemtime($dependency);
|
||||
}
|
||||
|
||||
cache_set('less:devel:' . drupal_hash_base64($input_file), $watched_files);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copied functionality from drupal_build_css_cache() for our own purposes.
|
||||
*
|
||||
* This function processes $contents and rewrites relative paths to be absolute
|
||||
* from web root. This is mainly used to ensure that compiled .less files still
|
||||
* reference images at their original paths.
|
||||
*
|
||||
* @param string $input_filepath
|
||||
* @param string $contents
|
||||
*
|
||||
* @return string
|
||||
* Processed styles with replaced paths.
|
||||
*
|
||||
* @see drupal_build_css_cache()
|
||||
*/
|
||||
function _less_rewrite_paths($input_filepath, $contents) {
|
||||
$output = '';
|
||||
|
||||
// Build the base URL of this CSS file: start with the full URL.
|
||||
$css_base_url = file_create_url($input_filepath);
|
||||
// Move to the parent.
|
||||
$css_base_url = substr($css_base_url, 0, strrpos($css_base_url, '/'));
|
||||
// Simplify to a relative URL if the stylesheet URL starts with the
|
||||
// base URL of the website.
|
||||
if (substr($css_base_url, 0, strlen($GLOBALS['base_root'])) == $GLOBALS['base_root']) {
|
||||
$css_base_url = substr($css_base_url, strlen($GLOBALS['base_root']));
|
||||
}
|
||||
|
||||
_drupal_build_css_path(NULL, $css_base_url . '/');
|
||||
// Anchor all paths in the CSS with its base URL, ignoring external and absolute paths.
|
||||
$output .= preg_replace_callback('/url\(\s*[\'"]?(?![a-z]+:|\/+)([^\'")]+)[\'"]?\s*\)/i', '_drupal_build_css_path', $contents);
|
||||
|
||||
return $output;
|
||||
}
|
116
sites/all/modules/less/includes/less.theme.inc
Normal file
116
sites/all/modules/less/includes/less.theme.inc
Normal file
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains alterations to theme settings forms.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_form_alter().
|
||||
*/
|
||||
function less_form_alter(&$form, &$form_state, $form_id) {
|
||||
|
||||
if ($form_id === 'system_theme_settings') {
|
||||
|
||||
preg_match('/^theme_(?P<current_theme_key>\w+)_settings$/', $form['var']['#value'], $matches);
|
||||
|
||||
// only show settings on forms for themes, not "Global settings"
|
||||
if (!empty($matches['current_theme_key'])) {
|
||||
|
||||
$current_theme_key = $matches['current_theme_key'];
|
||||
|
||||
$saved_settings = theme_get_setting('less', $current_theme_key);
|
||||
|
||||
$less_settings_form = array();
|
||||
|
||||
$theme_items = system_list('theme');
|
||||
|
||||
if (isset($theme_items[$current_theme_key]) && !empty($theme_items[$current_theme_key]->info['less']['vars'])) {
|
||||
$less_settings_form[$current_theme_key] = _less_setting_form_element($current_theme_key, $theme_items[$current_theme_key]->info['less']['vars'], $saved_settings[$current_theme_key]);
|
||||
}
|
||||
|
||||
// showing settings form for modules
|
||||
$system_items = system_list('module_enabled');
|
||||
|
||||
$less_module_settings = array();
|
||||
|
||||
foreach ($system_items as $system_item_name => $system_item) {
|
||||
|
||||
if (!empty($system_item->info['less']['vars'])) {
|
||||
|
||||
$item_saved_settings = isset($saved_settings[$system_item_name]) ? $saved_settings[$system_item_name] : array();
|
||||
|
||||
$less_module_settings[$system_item_name] = _less_setting_form_element($system_item_name, $system_item->info['less']['vars'], $item_saved_settings, $system_item->info['name']);
|
||||
$less_module_settings[$system_item_name]['#group'] = 'less][modules_list';
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($less_module_settings)) {
|
||||
|
||||
$less_settings_form['modules'] = array(
|
||||
'#type' => 'fieldset',
|
||||
'#title' => t('Modules'),
|
||||
'#collapsible' => TRUE,
|
||||
'#collapsed' => TRUE,
|
||||
'#parents' => array('less'),
|
||||
// make sure all settings are stored under the system name immediately inside the themes less settings array
|
||||
);
|
||||
|
||||
$less_settings_form['modules']['modules_list'] = array(
|
||||
'#type' => 'vertical_tabs',
|
||||
);
|
||||
|
||||
$less_settings_form['modules'] += $less_module_settings;
|
||||
|
||||
}
|
||||
|
||||
if (!empty($less_settings_form)) {
|
||||
|
||||
$form['less'] = array(
|
||||
'#type' => 'vertical_tabs',
|
||||
'#prefix' => t('<h3>LESS settings</h3>'),
|
||||
'#tree' => TRUE,
|
||||
'#description' => t('These settings are per theme. Delete a value to use the default.'),
|
||||
'#attached' => array(
|
||||
'css' => array(
|
||||
drupal_get_path('module', 'less') . '/styles/less.theme.css',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
$form['less'] += $less_settings_form;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _less_setting_form_element($system_name, $less_settings, $saved_settings, $title = NULL) {
|
||||
|
||||
$form = array(
|
||||
'#type' => 'fieldset',
|
||||
'#title' => isset($title) ? $title : $system_name,
|
||||
'#attributes' => array(
|
||||
'class' => array(
|
||||
'less-theme-settings',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
if (module_exists($system_name)) {
|
||||
|
||||
$less_settings = array_replace($less_settings, (array) module_invoke($system_name, 'less_variables'));
|
||||
}
|
||||
|
||||
foreach ($less_settings as $var_name => $var_value) {
|
||||
|
||||
$form[$var_name] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => $var_name,
|
||||
'#default_value' => !empty($saved_settings[$var_name]) ? $saved_settings[$var_name] : NULL,
|
||||
'#description' => t('Default value: %variable_value', array('%variable_value' => $var_value)),
|
||||
'#attributes' => array('placeholder' => $var_value),
|
||||
);
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
61
sites/all/modules/less/includes/less.watch.inc
Normal file
61
sites/all/modules/less/includes/less.watch.inc
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains page callback for LESS watch functionality.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Page callback for 'ajax/less/watch'.
|
||||
*
|
||||
* Handles AJAX requests to check for changes to files while in developer mode.
|
||||
*/
|
||||
function _less_watch() {
|
||||
|
||||
global $theme;
|
||||
|
||||
drupal_page_is_cacheable(FALSE);
|
||||
|
||||
$changed_files = array();
|
||||
|
||||
if (variable_get(LESS_WATCH, FALSE)) {
|
||||
|
||||
$files = (isset($_POST['less_files']) && is_array($_POST['less_files'])) ? $_POST['less_files'] : array();
|
||||
|
||||
foreach ($files as $file) {
|
||||
|
||||
$file_url_parts = drupal_parse_url($file);
|
||||
|
||||
if ($cache = cache_get('less:watch:' . drupal_hash_base64($file_url_parts['path']))) {
|
||||
|
||||
$cached_data = $cache->data;
|
||||
|
||||
$input_file = $cached_data['less']['input_file'];
|
||||
|
||||
$output_file = $cached_data['less']['output_file'];
|
||||
|
||||
$current_mtime = filemtime($output_file);
|
||||
|
||||
$theme = $cached_data['less']['theme'];
|
||||
|
||||
$styles = array(
|
||||
'#items' => array(
|
||||
$input_file => $cached_data,
|
||||
),
|
||||
);
|
||||
|
||||
$styles = _less_pre_render($styles);
|
||||
|
||||
if (filemtime($styles['#items'][$input_file]['data']) > $current_mtime) {
|
||||
$changed_files[] = array(
|
||||
'old_file' => $file_url_parts['path'],
|
||||
'new_file' => file_create_url($styles['#items'][$input_file]['data']),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $changed_files;
|
||||
}
|
||||
|
94
sites/all/modules/less/includes/less.wysiwyg.inc
Normal file
94
sites/all/modules/less/includes/less.wysiwyg.inc
Normal file
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains functions that handle WYSIWYG module integration.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_wysiwyg_editor_settings_alter().
|
||||
*
|
||||
* Check the CSS WYSIWYG setting for LESS files and replace with
|
||||
* generated CSS files where necessary.
|
||||
*/
|
||||
function less_wysiwyg_editor_settings_alter(&$settings, $context) {
|
||||
|
||||
$wysiwyg = $context['editor']['name'];
|
||||
|
||||
// Each editor has a different $settings array key for CSS files.
|
||||
$editors = array(
|
||||
'tinymce' => 'content_css',
|
||||
'fckeditor' => 'EditorAreaCSS',
|
||||
'ckeditor' => 'contentsCss',
|
||||
);
|
||||
|
||||
if (!empty($editors[$wysiwyg]) && !empty($settings[$editors[$wysiwyg]])) {
|
||||
|
||||
$stylesheets = $settings[$editors[$wysiwyg]];
|
||||
|
||||
// Keep track if comma separated paths, or array of paths.
|
||||
$is_array = is_array($stylesheets);
|
||||
|
||||
if ($is_array === FALSE) {
|
||||
|
||||
// $stylesheets is a list of comma separated file paths.
|
||||
$stylesheets = explode(',', $stylesheets);
|
||||
}
|
||||
|
||||
// Prepare an array that can be handled by normal LESS module processing.
|
||||
$styles = array(
|
||||
'#items' => array(),
|
||||
);
|
||||
|
||||
foreach ($stylesheets as $stylesheet) {
|
||||
|
||||
// Might contain ?query portion, separate parts.
|
||||
$parts = drupal_parse_url($stylesheet);
|
||||
|
||||
// Paths are expected to be relative to DRUPAL_ROOT, trim leading '/'.
|
||||
$path = trim($parts['path'], '/');
|
||||
|
||||
$styles['#items'][$path] = array(
|
||||
'data' => $path,
|
||||
);
|
||||
}
|
||||
|
||||
$styles = _less_pre_render($styles);
|
||||
|
||||
$processed_stylesheets = array();
|
||||
|
||||
foreach ($styles['#items'] as $file) {
|
||||
$processed_stylesheets[] = file_create_url($file['data']);
|
||||
}
|
||||
|
||||
// Recombine file paths into comma separated list.
|
||||
if ($is_array === FALSE) {
|
||||
$processed_stylesheets = implode(',', $processed_stylesheets);
|
||||
}
|
||||
|
||||
$settings[$editors[$wysiwyg]] = $processed_stylesheets;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_form_FORM_ID_alter().
|
||||
*
|
||||
* form_id = 'wysiwyg_profile'
|
||||
*/
|
||||
function less_form_wysiwyg_profile_form_alter(&$form, $form_state, $form_id) {
|
||||
$form['css']['css_path']['#description'] .= '<br />' . t('You may enter a path to a LESS file and it will be parsed automatically.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ckeditor_settings_alter().
|
||||
*/
|
||||
function less_ckeditor_settings_alter(&$settings) {
|
||||
|
||||
$context = array(
|
||||
'editor' => array(
|
||||
'name' => 'ckeditor',
|
||||
),
|
||||
);
|
||||
|
||||
less_wysiwyg_editor_settings_alter($settings, $context);
|
||||
}
|
Reference in New Issue
Block a user