View source
<?php
define('SASSY_PRECOMPILE', 'SASSY_PRECOMPILE');
define('SASSY_POSTCOMPILE', 'SASSY_POSTCOMPILE');
function sassy_flush_caches() {
sassy_clear_cache();
}
function sassy_element_info_alter(&$type) {
array_unshift($type['styles']['#pre_render'], 'sassy_pre_render');
if (variable_get('sassy_devel', FALSE) && user_access('administer site configuration') && flood_is_allowed('sassy_devel_warning', 1)) {
flood_register_event('sassy_devel_warning');
drupal_set_message(t('Your SASS / SCSS files are being recompiled on every page request. Don\'t forget to <a href="!link">disable this feature</a> before opening your website to the public.', array(
'!link' => url('admin/config/development/performance'),
)), 'warning');
}
}
function sassy_form_system_performance_settings_alter(&$form, &$form_states) {
$form['sassy'] = array(
'#type' => 'fieldset',
'#title' => t('Development settings for the SASSY module'),
);
$form['sassy']['sassy_devel'] = array(
'#type' => 'checkbox',
'#title' => t('Recompile all SASS / SCSS files on every page request.'),
'#description' => t('Disables the caching of SASS / SCSS files. Useful for when regularly changing the stylesheets (during theme development).'),
'#default_value' => variable_get('sassy_devel', FALSE),
);
}
function sassy_pre_render($elements) {
$map = $original = variable_get('sassy_cache', array());
$devel = variable_get('sassy_devel', FALSE);
foreach ($elements['#items'] as $key => $file) {
if ($file['type'] == 'file' && in_array(drupal_substr($file['data'], -5), array(
'.scss',
'.sass',
))) {
$file['recompile'] = isset($file['recompile']) ? $file['recompile'] : FALSE;
$file['preprocess'] = !empty($file['recompile']) ? FALSE : $file['preprocess'];
if ($file['recompile'] !== TRUE) {
$hash = hash('sha256', serialize($file));
$path = isset($map[$hash]) ? $map[$hash] : NULL;
}
if ($devel || $file['recompile'] === TRUE || !isset($path) || !file_exists($path)) {
$syntax = drupal_substr($file['data'], -4);
if (!($output = sassy_parse($file['data'], $syntax, $devel))) {
unset($elements['#items'][$key]);
continue;
}
$directory = 'public://sassy';
$path = $directory . '/' . drupal_hash_base64($output) . '.css';
file_prepare_directory($directory, FILE_CREATE_DIRECTORY);
if (!file_exists($path) && !file_unmanaged_save_data($output, $path, FILE_EXISTS_REPLACE)) {
unset($elements['#items'][$key]);
continue;
}
}
$elements['#items'][$key] = $file;
$elements['#items'][$key]['data'] = $path;
if ($file['recompile'] !== TRUE) {
$map[$hash] = $path;
}
}
}
if ($original !== $map) {
variable_set('sassy_cache', $map);
}
return $elements;
}
function sassy_clear_cache() {
variable_del('sassy_cache');
file_scan_directory('public://sassy', '/.*/', array(
'callback' => 'drupal_delete_file_if_stale',
));
}
function sassy_parse($file, $syntax, $debug = FALSE) {
if (module_load_include('php', 'sassy', 'phpsass/SassParser')) {
try {
$options = array(
'style' => 'nested',
'cache' => FALSE,
'syntax' => $syntax,
'debug' => $debug,
'load_path_functions' => array(
'sassy_load_callback',
),
'functions' => sassy_get_functions(),
);
$parser = new SassParser($options);
return $parser
->toCss($file);
} catch (Exception $e) {
watchdog_exception('sassy', $e);
if (user_access('administer site configuration')) {
drupal_set_message(t('An error occured while processing !stylesheet. Please consult your !watchdog for a detailed error description.', array(
'!stylesheet' => l(basename($file), $file),
'!watchdog' => l('log messages', 'admin/reports/dblog'),
)), 'error');
}
}
}
}
function sassy_get_functions() {
$functions =& drupal_static(__FUNCTION__);
if (!isset($function)) {
foreach (module_invoke_all('sassy_functions') as $name => $info) {
$info = (object) $info;
$functions[$info->name] = $info->callback;
}
foreach (array_merge($GLOBALS['base_theme_info'], array(
$GLOBALS['theme_info'],
)) as $info) {
$function = $info->info['name'] . '_sassy_functions';
if (function_exists($function) && ($data = $function())) {
foreach ($data as $key => $item) {
$info = (object) $info;
$functions[$info->name] = $info->callback;
}
}
}
}
return $functions;
}
function sassy_load_callback($file) {
$file = explode('/', $file, 2);
$namespace = preg_replace('/[^0-9a-z]+/i', '_', array_shift($file));
foreach (module_implements('sassy_resolve_path_' . $namespace) as $module) {
$hook = $module . '_sassy_resolve_path_' . $namespace;
if (function_exists($hook) && ($paths = call_user_func($hook, $file[0]))) {
return (array) $paths;
}
}
return FALSE;
}
function sassy_sassy_resolve_path_sassy($file) {
return sassy_registered_includes(basename($file));
}
function sassy_registered_includes($base = NULL) {
$includes =& drupal_static(__FUNCTION__);
if (!isset($includes)) {
if ($cache = cache_get('sassy_libraries:' . $GLOBALS['theme_key'])) {
$includes = $cache->data;
}
else {
$includes = array();
foreach (array_merge(module_list(), $GLOBALS['base_theme_info'], array(
$GLOBALS['theme_info'],
)) as $info) {
$type = is_object($info) ? 'theme' : 'module';
$name = $type == 'theme' ? $info->name : $info;
$info = $type == 'theme' ? $info->info : system_get_info('module', $name);
if (!empty($info['sassy'])) {
foreach ($info['sassy'] as $include) {
$path = drupal_get_path($type, $name) . '/' . $include;
if (is_file($path)) {
$includes[basename($path)][] = $path;
}
}
}
}
drupal_alter('sassy_includes', $includes);
cache_set('sassy_includes:' . $GLOBALS['theme_key'], $includes);
}
}
if (isset($base) && isset($includes[$base])) {
return $includes[$base];
}
else {
if (!isset($base)) {
return $includes;
}
}
}