117
wp-content/plugins/all-in-one-event-calendar/lib/css/admin.php
Normal file
117
wp-content/plugins/all-in-one-event-calendar/lib/css/admin.php
Normal file
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* The class which handles Admin CSS.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.Css
|
||||
*/
|
||||
class Ai1ec_Css_Admin extends Ai1ec_Base {
|
||||
|
||||
/**
|
||||
* Enqueue any scripts and styles in the admin side, depending on context.
|
||||
*
|
||||
* @wp_hook admin_enqueue_scripts
|
||||
*
|
||||
*/
|
||||
public function admin_enqueue_scripts( $hook_suffix ) {
|
||||
$settings = $this->_registry->get( 'model.settings' );
|
||||
$enqueuables = array(
|
||||
'widgets.php' => array(
|
||||
array( 'style', 'widget.css', ),
|
||||
),
|
||||
'edit-tags.php' => array(
|
||||
array( 'style', 'colorpicker.css', ),
|
||||
array( 'style', 'bootstrap.min.css', ),
|
||||
array( 'style', 'taxonomies.css', ),
|
||||
),
|
||||
'term.php' => array(
|
||||
array( 'style', 'colorpicker.css', ),
|
||||
array( 'style', 'bootstrap.min.css', ),
|
||||
array( 'style', 'taxonomies.css', ),
|
||||
),
|
||||
$settings->get( 'settings_page' ) => array(
|
||||
array( 'script', 'common', ),
|
||||
array( 'script', 'wp-lists', ),
|
||||
array( 'script', 'postbox', ),
|
||||
array( 'style', 'settings.css', ),
|
||||
array( 'style', 'bootstrap.min.css', ),
|
||||
),
|
||||
$settings->get( 'feeds_page' ) => array(
|
||||
array( 'script', 'common', ),
|
||||
array( 'script', 'wp-lists', ),
|
||||
array( 'script', 'postbox', ),
|
||||
array( 'style', 'settings.css', ),
|
||||
array( 'style', 'bootstrap.min.css', ),
|
||||
array( 'style', 'plugins/plugins-common.css', ),
|
||||
),
|
||||
$settings->get( 'less_variables_page' ) => array(
|
||||
array( 'style', 'settings.css', ),
|
||||
array( 'style', 'bootstrap.min.css', ),
|
||||
array( 'style', 'bootstrap_colorpicker.css', ),
|
||||
),
|
||||
);
|
||||
|
||||
if ( isset( $enqueuables[$hook_suffix] ) ) {
|
||||
return $this->process_enqueue( $enqueuables[$hook_suffix] );
|
||||
}
|
||||
|
||||
$aco = $this->_registry->get( 'acl.aco' );
|
||||
$post_pages = array( 'post.php' => true, 'post-new.php' => true );
|
||||
|
||||
if (
|
||||
isset( $post_pages[$hook_suffix] ) ||
|
||||
$aco->are_we_editing_our_post()
|
||||
) {
|
||||
return $this->process_enqueue(
|
||||
array(
|
||||
array( 'style', 'bootstrap.min.css', ),
|
||||
array( 'style', 'add_new_event.css', ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue scripts and styles.
|
||||
*
|
||||
* @param array $item_list List of scripts/styles to enqueue.
|
||||
*
|
||||
* @return bool Always true
|
||||
*/
|
||||
public function process_enqueue( array $item_list ) {
|
||||
foreach ( $item_list as $item ) {
|
||||
if ( 'script' === $item[0] ) {
|
||||
wp_enqueue_script( $item[1] );
|
||||
} else {
|
||||
wp_enqueue_style(
|
||||
$this->gen_style_hook( $item[1] ),
|
||||
AI1EC_ADMIN_THEME_CSS_URL . $item[1],
|
||||
array(),
|
||||
AI1EC_VERSION
|
||||
);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a style hook for use with WordPress.
|
||||
*
|
||||
* @param string $script Name of enqueable script.
|
||||
*
|
||||
* @return string Hook to use with WordPress.
|
||||
*/
|
||||
public function gen_style_hook( $script ) {
|
||||
return 'ai1ec_' . preg_replace(
|
||||
'|[^a-z]+|',
|
||||
'_',
|
||||
basename( $script, '.css' )
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,376 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* The class which handles Frontend CSS.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.Css
|
||||
*/
|
||||
class Ai1ec_Css_Frontend extends Ai1ec_Base {
|
||||
|
||||
const QUERY_STRING_PARAM = 'ai1ec_render_css';
|
||||
|
||||
// This is for testing purpose, set it to AI1EC_PARSE_LESS_FILES_AT_EVERY_REQUEST value.
|
||||
const PARSE_LESS_FILES_AT_EVERY_REQUEST = AI1EC_PARSE_LESS_FILES_AT_EVERY_REQUEST;
|
||||
|
||||
const KEY_FOR_PERSISTANCE = 'ai1ec_parsed_css';
|
||||
/**
|
||||
* @var Ai1ec_Persistence_Context
|
||||
*/
|
||||
private $persistance_context;
|
||||
|
||||
/**
|
||||
* @var Ai1ec_Less_Lessphp
|
||||
*/
|
||||
private $lessphp_controller;
|
||||
|
||||
/**
|
||||
* @var Ai1ec_Option
|
||||
*/
|
||||
private $db_adapter;
|
||||
|
||||
/**
|
||||
* @var Ai1ec_Template_Adapter
|
||||
*/
|
||||
private $template_adapter;
|
||||
|
||||
/**
|
||||
* Possible paths/url for file cache
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_cache_paths = array();
|
||||
|
||||
/**
|
||||
* @var array which have been checked and are not writable
|
||||
*/
|
||||
protected $_folders_not_writable = array();
|
||||
|
||||
public function __construct(
|
||||
Ai1ec_Registry_Object $registry
|
||||
) {
|
||||
parent::__construct( $registry );
|
||||
$this->_cache_paths[] = array(
|
||||
'path' => AI1EC_CACHE_PATH,
|
||||
'url' => AI1EC_CACHE_URL
|
||||
);
|
||||
if ( apply_filters( 'ai1ec_check_static_dir', true ) ) {
|
||||
$filesystem = $this->_registry->get( 'filesystem.checker' );
|
||||
$wp_static_folder = $filesystem->get_ai1ec_static_dir_if_available();
|
||||
if ( '' !== $wp_static_folder ) {
|
||||
$this->_cache_paths[] = array(
|
||||
'path' => $wp_static_folder,
|
||||
'url' => content_url() . '/uploads/ai1ec_static/'
|
||||
);
|
||||
}
|
||||
}
|
||||
$this->persistance_context = $this->_registry->get(
|
||||
'cache.strategy.persistence-context',
|
||||
self::KEY_FOR_PERSISTANCE,
|
||||
$this->_cache_paths,
|
||||
true
|
||||
);
|
||||
if ( ! $this->persistance_context->is_file_cache() ) {
|
||||
/* @TODO: move this to Settings -> Advanced -> Cache */
|
||||
}
|
||||
$this->lessphp_controller = $this->_registry->get( 'less.lessphp' );
|
||||
$this->db_adapter = $this->_registry->get( 'model.option' );
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Get if file cache is enabled
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_file_cache_enabled() {
|
||||
return $this->persistance_context->is_file_cache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get folders which are not writable
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_folders_not_writable() {
|
||||
return $this->_folders_not_writable;
|
||||
}
|
||||
/**
|
||||
* Renders the css for our frontend.
|
||||
*
|
||||
* Sets etags to avoid sending not needed data
|
||||
*/
|
||||
public function render_css() {
|
||||
header( 'HTTP/1.1 200 OK' );
|
||||
header( 'Content-Type: text/css', true, 200 );
|
||||
// Aggressive caching to save future requests from the same client.
|
||||
$etag = '"' . md5( __FILE__ . $_GET[self::QUERY_STRING_PARAM] ) . '"';
|
||||
header( 'ETag: ' . $etag );
|
||||
$max_age = 31536000;
|
||||
$time_sys = $this->_registry->get( 'date.system' );
|
||||
header(
|
||||
'Expires: ' .
|
||||
gmdate(
|
||||
'D, d M Y H:i:s',
|
||||
$time_sys->current_time() + $max_age
|
||||
) .
|
||||
' GMT'
|
||||
);
|
||||
header( 'Cache-Control: public, max-age=' . $max_age );
|
||||
if (
|
||||
empty( $_SERVER['HTTP_IF_NONE_MATCH'] ) ||
|
||||
$etag !== stripslashes( $_SERVER['HTTP_IF_NONE_MATCH'] )
|
||||
) {
|
||||
// compress data if possible
|
||||
$this->_registry->get( 'compatibility.ob' )
|
||||
->gzip_if_possible( $this->get_compiled_css() );
|
||||
} else {
|
||||
// Not modified!
|
||||
status_header( 304 );
|
||||
}
|
||||
// We're done!
|
||||
Ai1ec_Http_Response_Helper::stop( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $css
|
||||
* @throws Ai1ec_Cache_Write_Exception
|
||||
*/
|
||||
public function update_persistence_layer( $css ) {
|
||||
$filename = $this->persistance_context->write_data_to_persistence( $css );
|
||||
$this->db_adapter->set(
|
||||
'ai1ec_filename_css',
|
||||
isset( $filename['file'] ) ? $filename['file'] : false,
|
||||
true
|
||||
);
|
||||
$this->save_less_parse_time( $filename['url'] );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the url to retrieve the css
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_css_url() {
|
||||
// get what's saved. I t could be false, a int or a string.
|
||||
// if it's false or a int, use PHP to render CSS
|
||||
$saved_par = $this->db_adapter->get( self::QUERY_STRING_PARAM );
|
||||
// if it's empty it's a new install probably. Return static css.
|
||||
// if it's numeric, just consider it a new install
|
||||
if ( empty( $saved_par ) ) {
|
||||
$theme = $this->_registry->get(
|
||||
'model.option'
|
||||
)->get( 'ai1ec_current_theme' );
|
||||
return Ai1ec_Http_Response_Helper::remove_protocols(
|
||||
apply_filters(
|
||||
'ai1ec_frontend_standard_css_url',
|
||||
$theme['theme_url'] . '/css/ai1ec_parsed_css.css'
|
||||
)
|
||||
);
|
||||
}
|
||||
if ( is_numeric( $saved_par ) ) {
|
||||
if ( $this->_registry->get( 'model.settings' )->get( 'render_css_as_link' ) ) {
|
||||
$time = (int) $saved_par;
|
||||
$template_helper = $this->_registry->get( 'template.link.helper' );
|
||||
return Ai1ec_Http_Response_Helper::remove_protocols(
|
||||
add_query_arg(
|
||||
array( self::QUERY_STRING_PARAM => $time, ),
|
||||
trailingslashit( ai1ec_get_site_url() )
|
||||
)
|
||||
);
|
||||
} else {
|
||||
add_action( 'wp_head', array( $this, 'echo_css' ) );
|
||||
return '';
|
||||
}
|
||||
|
||||
}
|
||||
// otherwise return the string
|
||||
return Ai1ec_Http_Response_Helper::remove_protocols(
|
||||
$saved_par
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the link that will be added to the frontend
|
||||
*/
|
||||
public function add_link_to_html_for_frontend() {
|
||||
$url = $this->get_css_url();
|
||||
if ( '' !== $url && ! is_admin() ) {
|
||||
wp_enqueue_style( 'ai1ec_style', $url, array(), AI1EC_VERSION );
|
||||
}
|
||||
}
|
||||
|
||||
public function echo_css() {
|
||||
echo '<style>';
|
||||
echo $this->get_compiled_css();
|
||||
echo '</style>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate the persistence layer only after a successful compile of the
|
||||
* LESS files.
|
||||
*
|
||||
* @param array $variables LESS variable array to use
|
||||
* @param boolean $update_persistence Whether the persist successful compile
|
||||
*
|
||||
* @return boolean Whether successful
|
||||
*/
|
||||
public function invalidate_cache(
|
||||
array $variables = null,
|
||||
$update_persistence = false
|
||||
) {
|
||||
if ( ! $this->lessphp_controller->is_compilation_needed( $variables ) ) {
|
||||
$this->_registry->get(
|
||||
'model.option'
|
||||
)->delete( 'ai1ec_render_css' );
|
||||
return true;
|
||||
}
|
||||
$notification = $this->_registry->get( 'notification.admin' );
|
||||
if (
|
||||
! $this->_registry->get(
|
||||
'compatibility.memory'
|
||||
)->check_available_memory( AI1EC_LESS_MIN_AVAIL_MEMORY )
|
||||
) {
|
||||
$message = sprintf(
|
||||
Ai1ec_I18n::__(
|
||||
'CSS compilation failed because you don\'t have enough free memory (a minimum of %s is needed). Your calendar will not render or function properly without CSS. Please read <a href="https://time.ly/document/user-guide/getting-started/pre-sale-questions/">this article</a> to learn how to increase your PHP memory limit.'
|
||||
),
|
||||
AI1EC_LESS_MIN_AVAIL_MEMORY
|
||||
);
|
||||
$notification->store(
|
||||
$message,
|
||||
'error',
|
||||
1,
|
||||
array( Ai1ec_Notification_Admin::RCPT_ADMIN ),
|
||||
true
|
||||
);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
// Try to parse the css
|
||||
$css = $this->lessphp_controller->parse_less_files( $variables );
|
||||
// Reset the parse time to force a browser reload of the CSS, whether we are
|
||||
// updating persistence or not. Do it here to be sure files compile ok.
|
||||
$this->save_less_parse_time();
|
||||
if ( $update_persistence ) {
|
||||
$this->update_persistence_layer( $css );
|
||||
} else {
|
||||
$this->persistance_context->delete_data_from_persistence();
|
||||
}
|
||||
} catch ( Ai1ec_Cache_Write_Exception $e ) {
|
||||
// This means successful during parsing but problems persisting the CSS.
|
||||
$message = '<p>' . Ai1ec_I18n::__( "The LESS file compiled correctly but there was an error while saving the generated CSS to persistence." ) . '</p>';
|
||||
$notification->store( $message, 'error' );
|
||||
return false;
|
||||
} catch ( Exception $e ) {
|
||||
// An error from lessphp.
|
||||
$message = sprintf(
|
||||
Ai1ec_I18n::__( '<p><strong>There was an error while compiling CSS.</strong> The message returned was: <em>%s</em></p>' ),
|
||||
$e->getMessage()
|
||||
);
|
||||
$notification->store( $message, 'error', 1 );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update the less variables on the DB and recompile the CSS
|
||||
*
|
||||
* @param array $variables
|
||||
* @param boolean $resetting are we resetting or updating variables?
|
||||
*/
|
||||
public function update_variables_and_compile_css( array $variables, $resetting ) {
|
||||
$no_parse_errors = $this->invalidate_cache( $variables, true );
|
||||
$notification = $this->_registry->get( 'notification.admin' );
|
||||
|
||||
if ( $no_parse_errors ) {
|
||||
$this->db_adapter->set(
|
||||
Ai1ec_Less_Lessphp::DB_KEY_FOR_LESS_VARIABLES,
|
||||
$variables
|
||||
);
|
||||
|
||||
if ( true === $resetting ) {
|
||||
$message = sprintf(
|
||||
'<p>' . Ai1ec_I18n::__(
|
||||
"Theme options were successfully reset to their default values. <a href='%s'>Visit site</a>"
|
||||
) . '</p>',
|
||||
ai1ec_get_site_url()
|
||||
);
|
||||
} else {
|
||||
$message = sprintf(
|
||||
'<p>' .Ai1ec_I18n::__(
|
||||
"Theme options were updated successfully. <a href='%s'>Visit site</a>"
|
||||
) . '</p>',
|
||||
ai1ec_get_site_url()
|
||||
);
|
||||
}
|
||||
|
||||
$notification->store( $message );
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Try to get the CSS from cache.
|
||||
* If it's not there re-generate it and save it to cache
|
||||
* If we are in preview mode, recompile the css using the theme present in the url.
|
||||
*
|
||||
*/
|
||||
public function get_compiled_css() {
|
||||
try {
|
||||
// If we want to force a recompile, we throw an exception.
|
||||
if( self::PARSE_LESS_FILES_AT_EVERY_REQUEST === true ) {
|
||||
throw new Ai1ec_Cache_Not_Set_Exception();
|
||||
}else {
|
||||
// This throws an exception if the key is not set
|
||||
$css = $this->persistance_context->get_data_from_persistence();
|
||||
return $css;
|
||||
}
|
||||
} catch ( Ai1ec_Cache_Not_Set_Exception $e ) {
|
||||
$css = $this->lessphp_controller->parse_less_files();
|
||||
try {
|
||||
$this->update_persistence_layer( $css );
|
||||
return $css;
|
||||
} catch ( Ai1ec_Cache_Write_Exception $e ) {
|
||||
if ( ! self::PARSE_LESS_FILES_AT_EVERY_REQUEST ) {
|
||||
$this->_registry->get( 'notification.admin' )
|
||||
->store(
|
||||
sprintf(
|
||||
__(
|
||||
'Your CSS is being compiled on every request, which causes your calendar to perform slowly. The following error occurred: %s',
|
||||
AI1EC_PLUGIN_NAME
|
||||
),
|
||||
$e->getMessage()
|
||||
),
|
||||
'error',
|
||||
2,
|
||||
array( Ai1ec_Notification_Admin::RCPT_ADMIN ),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
// If something is really broken, still return the css.
|
||||
// This means we parse it every time. This should never happen.
|
||||
return $css;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the path to the CSS file or false to load standard CSS
|
||||
*/
|
||||
private function save_less_parse_time( $data = false ) {
|
||||
$to_save = is_string( $data ) ?
|
||||
$data :
|
||||
$this->_registry->get( 'date.system' )->current_time();
|
||||
$this->db_adapter->set(
|
||||
self::QUERY_STRING_PARAM,
|
||||
$to_save,
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user