mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
3469e4d22a
------------------------------------------------------------------------ r68900 | sminnee | 2008-12-15 14:30:41 +1300 (Mon, 15 Dec 2008) | 1 line Static caching merges from dnc branch ------------------------------------------------------------------------ r68917 | sminnee | 2008-12-15 14:49:06 +1300 (Mon, 15 Dec 2008) | 1 line Merged Requirements fix from nestedurls branch ------------------------------------------------------------------------ r70033 | aoneil | 2009-01-13 14:03:41 +1300 (Tue, 13 Jan 2009) | 2 lines Add translation migration task ------------------------------------------------------------------------ r70072 | ischommer | 2009-01-13 17:34:27 +1300 (Tue, 13 Jan 2009) | 5 lines API CHANGE Removed obsolete internal Translatable methods: hasOwnTranslatableFields(), allFieldsInTable() ENHANCEMENT Removed $create flag in Translatable::getTranslation() and replaced with explit action createTranslation() ENHANCEMENT Sorting return array of Translatable::getTranslatedLangs() ENHANCEMENT Added a note about saving a page before creating a translation MINOR Added phpdoc to Translatable ------------------------------------------------------------------------ r70073 | ischommer | 2009-01-13 17:34:45 +1300 (Tue, 13 Jan 2009) | 1 line ENHANCEMENT Added basic unit tests to new Translatable API ------------------------------------------------------------------------ r70080 | aoneil | 2009-01-13 18:04:21 +1300 (Tue, 13 Jan 2009) | 3 lines BUGFIX: Fix translatable migration regenerating URLSegments when it shouldn't BUGFIX: Fix translatable migration not writing records to Live properly ------------------------------------------------------------------------ r70118 | ischommer | 2009-01-14 11:28:24 +1300 (Wed, 14 Jan 2009) | 3 lines API CHANGE Removed obsolete Translatable::table_exists() ENHANCEMENT Made Translatable constructor arguments optional, as by default all database fields are marked translatable MINOR More unit tests for Translatable ------------------------------------------------------------------------ r70138 | ischommer | 2009-01-14 17:00:30 +1300 (Wed, 14 Jan 2009) | 1 line BUGFIX Disabled assumption that SQLQuery->filtersOnID() should only kick in when exactly one WHERE clause is given - this is very fragile and hard to test. It would return TRUE on $where = "SiteTree.ID = 5", but not on $where = array("Lang = 'de'", "SiteTree.ID = 5") ------------------------------------------------------------------------ r70214 | ischommer | 2009-01-15 18:56:25 +1300 (Thu, 15 Jan 2009) | 3 lines BUGFIX Falling back to Translatable::current_lang() if no $context object is given, in augmentAllChildrenIncludingDeleted() and AllChildrenIncludingDeleted() MINOR phpdoc for Translatable MINOR Added more Translatable unit tests ------------------------------------------------------------------------ r70306 | ischommer | 2009-01-16 17:14:34 +1300 (Fri, 16 Jan 2009) | 9 lines ENHANCEMENT Recursively creating translations for parent pages to ensure that a translated page is still accessible by traversing the tree, e.g. in "cms translation mode" (in Translatable->onBeforeWrite()) ENHANCEMENT Simplified AllChildrenIncludingDeleted() to not require a special augmentAllChildrenIncludingDeleted() implementation: We don't combine untranslated/translated children any longer (which was used in CMS tree view), but rather just show translated records ENHANCEMENT Ensuring uniqueness of URL segments by appending "-<langcode>" to new translations (in Translatable->onBeforeWrite()) ENHANCEMENT Added Translatable->alternateGetByUrl() as a hook into SiteTree::get_by_url() ENHANCEMENT Adding link back to original page in CMS editform for translations BUGFIX Excluding HiddenField instances from Translatable->updateCMSFields() BUGFIX Don't require a record to be written (through exists()) when checking Translatable->isTranslation() or Translatable->hasTranslation() MINOR Don't use createMethod() shortcut for Translatable->AllChildrenIncludingDeleted() MINOR Added Translatable unit tests ------------------------------------------------------------------------ r70318 | ischommer | 2009-01-19 11:46:16 +1300 (Mon, 19 Jan 2009) | 1 line BUGFIX Reverted special cases for Translatable in Versioned->canBeVersioned() (originally committed in r42119) - was checking for existence of underscores in table names as an indication of the "_lang" suffix, which is no longer needed. It was also a flawed assumption which tripped over classes like TranslatableTest_TestPage ------------------------------------------------------------------------ r70319 | ischommer | 2009-01-19 11:47:02 +1300 (Mon, 19 Jan 2009) | 1 line ENHANCEMENT Disabled Translatab-e>augmentWrite() - was only needed for the blacklist fields implementation which is inactive for the moment ------------------------------------------------------------------------ r70326 | ischommer | 2009-01-19 14:25:23 +1300 (Mon, 19 Jan 2009) | 2 lines ENHANCEMENT Making ErrorPage static HTML files translatable (#2233) ENHANCEMENT Added ErrorPage::$static_filepath to flexibly set location of static error pages (defaults to /assets) ------------------------------------------------------------------------ r70327 | ischommer | 2009-01-19 15:18:41 +1300 (Mon, 19 Jan 2009) | 1 line FEATURE Enabled specifying a language through a hidden field in SearchForm which limits the search to pages in this language (incl. unit tests) ------------------------------------------------------------------------ r71258 | sharvey | 2009-02-03 15:49:34 +1300 (Tue, 03 Feb 2009) | 2 lines BUGFIX: Fix translatable being enabled when it shouldn't be ------------------------------------------------------------------------ r71340 | ischommer | 2009-02-04 14:36:12 +1300 (Wed, 04 Feb 2009) | 1 line BUGFIX Including Hierarchy->children in flushCache() and renamed to _cache_children. This caused problems in TranslatableTest when re-using the same SiteTree->Children() method with different languages on the same object (even with calling flushCache() inbetween the calls) ------------------------------------------------------------------------ r71567 | gmunn | 2009-02-10 13:49:16 +1300 (Tue, 10 Feb 2009) | 1 line 'URLSegment' on line 484 and 494 now escaped ------------------------------------------------------------------------ r72054 | ischommer | 2009-02-23 10:30:41 +1300 (Mon, 23 Feb 2009) | 3 lines BUGFIX Fixed finding a translated homepage without an explicit URLSegment (e.g. http://mysite.com/?lang=de) - see #3540 ENHANCEMENT Added Translatable::get_homepage_urlsegment_by_language() ENHANCEMENT Added RootURLController::get_default_homepage_urlsegment() ------------------------------------------------------------------------ r72367 | ischommer | 2009-03-03 11:13:30 +1300 (Tue, 03 Mar 2009) | 2 lines ENHANCEMENT Added i18n::get_lang_from_locale() and i18n::convert_rfc1766() ENHANCEMENT Using IETF/HTTP compatible "long" language code in SiteTree->MetaTags(). This means the default <meta type="content-language..."> value will be "en-US" instead of "en". The locale can be either set through the Translatable content language, or through i18n::set_locale() ------------------------------------------------------------------------ r73036 | sminnee | 2009-03-14 13:16:32 +1300 (Sat, 14 Mar 2009) | 1 line ENHANCEMENT #3032 ajshort: Use static methods for accessing static data ------------------------------------------------------------------------ r73059 | sminnee | 2009-03-15 14:09:59 +1300 (Sun, 15 Mar 2009) | 2 lines ENHANCEMENT: Added Object::clearCache() to clear a cache BUGFIX: Make object cache testing more robust ------------------------------------------------------------------------ r73338 | ischommer | 2009-03-19 05:13:40 +1300 (Thu, 19 Mar 2009) | 9 lines API CHANGE Added concept of "translation groups" to Translatable- every page can belong to a group of related translations, rather than having an explicit "original", meaning you can have pages in "non-default" languages which have no representation in other language trees. This group is recorded in a new table "<classname>_translationgroups". Translatable->createTranslation() and Translatable->onBeforeWrite() will automatically associate records in this groups. Added Translatable->addTranslationGroup(), Translatable->removeTranslationGroup(), Translatable->getTranslationGroup() API CHANGE Removed Translatable->isTranslation() - after the new "translation group" model, every page is potentially a translation API CHANGE Translatable->findOriginalIDs(), Translatable->setOriginalPage(), Translatable->getOriginalPage() ENHANCEMENT Translatable->getCMSFields() will now always show the "create translation" option, not only on default languages - meaning you can create translations based on other translations ENHANCEMENT Translatable language dropdown in CMS will always show all available languages, rather than filtering by already existing translations ENHANCEMENT Added check for an existing record in Translatable->createTranslation() BUGFIX Removed Translatable->getLang() which overloaded the $db property - it was causing side effects during creation of SiteTree default records. BUGFIX Added check in Translatable->augmentSQL() to avoid reapplying "Lang = ..." filter twice BUGFIX Removed bypass in Translatable->AllChildrenIncludingDeleted() ------------------------------------------------------------------------ r73339 | ischommer | 2009-03-19 05:15:46 +1300 (Thu, 19 Mar 2009) | 1 line BUGFIX Disabled "untranslated" CSS class for SiteTree elements - doesn't apply any longer with the new "translation groups" concept ------------------------------------------------------------------------ r73341 | ischommer | 2009-03-19 06:01:51 +1300 (Thu, 19 Mar 2009) | 1 line BUGFIX Disabled auto-excluding of default language from the "available languages" array in LanguageDropdownField - due to the new "translation groups" its possible to have a translation from another language into the default language ------------------------------------------------------------------------ r73342 | ischommer | 2009-03-19 06:13:23 +1300 (Thu, 19 Mar 2009) | 4 lines BUGFIX Setting ParentID of translated record if recursively creating parents in Translatable::onBeforeWrite() BUGFIX Fixing inline form action for "create translation" BUGFIX Removed link to "original page" for a translation - no longer valid MINOR documentation for Translatable ------------------------------------------------------------------------ r73464 | ischommer | 2009-03-20 20:51:00 +1300 (Fri, 20 Mar 2009) | 1 line MINOR documentation ------------------------------------------------------------------------ r73465 | ischommer | 2009-03-20 20:58:52 +1300 (Fri, 20 Mar 2009) | 1 line BUGFIX Fixed Hierarchy->Children() testing in TranslatableTest - with the new datamodel you can't call Children() in a different language regardless of Translatable::set_reading_lang(), the Children() call has to be made from a parent in the same language ------------------------------------------------------------------------ r73466 | ischommer | 2009-03-20 21:36:40 +1300 (Fri, 20 Mar 2009) | 2 lines ENHANCEMENT Added Translatable::get_locale_from_lang(), Translatable::get_common_locales(), $common_locales and $likely_subtags in preparation to switch Translatable from using short "lang" codes to proper long locales API CHANGE Deprecated Translatable::set_default_lang(), Translatable::default_lang() ------------------------------------------------------------------------ r73467 | ischommer | 2009-03-20 21:38:57 +1300 (Fri, 20 Mar 2009) | 1 line ENHANCEMENT Supporting "Locale-English" and "Locale-Native" as listing arguments in LanguageDropdownField ------------------------------------------------------------------------ r73468 | ischommer | 2009-03-20 21:47:06 +1300 (Fri, 20 Mar 2009) | 7 lines ENHANCEMENT Adjusted SearchForm, Debug, ErrorPage, SiteTree to using locales instead of lang codes API CHANGE Changed Translatable datamodel to use locales ("en_US") instead of lang values ("en). API CHANGE Changed Translatable::$default_lang to $default_locale, Translatable::$reading_lang to $reading_locale API CHANGE Using "locale" instead of "lang" in Translatable::choose_site_lang() to auto-detect language from cookies or GET parameters API CHANGE Deprecated Translatable::is_default_lang(), set_default_lang(), get_default_lang(), current_lang(), set_reading_lang(), get_reading_lang(), get_by_lang(), get_one_by_lang() API CHANGE Removed Translatable::get_original() - with the new "translation groups" concept there no longer is an original for a translation BUGFIX Updated MigrateTranslatableTask to new Locale based datamodel ------------------------------------------------------------------------ r73470 | ischommer | 2009-03-20 21:56:57 +1300 (Fri, 20 Mar 2009) | 1 line MINOR fixed typo ------------------------------------------------------------------------ r73472 | sminnee | 2009-03-21 17:30:04 +1300 (Sat, 21 Mar 2009) | 1 line BUGFIX: Fixed translatable test execution by making protected methods public ------------------------------------------------------------------------ r73473 | sminnee | 2009-03-21 18:10:05 +1300 (Sat, 21 Mar 2009) | 1 line ENHANCEMENT: Added Object::combined_static(), which gets all values of a static property from each class in the hierarchy ------------------------------------------------------------------------ r73883 | ischommer | 2009-04-01 08:32:19 +1300 (Wed, 01 Apr 2009) | 1 line BUGFIX Making $_SINGLETONS a global instead of a static in Core.php so it can be re-used in other places ------------------------------------------------------------------------ r73951 | ischommer | 2009-04-02 05:35:32 +1300 (Thu, 02 Apr 2009) | 3 lines API CHANGE Deprecated Translatable::enable() and i18n::enable()- use Object::add_extension('SiteTree','Translatable'), Deprecated Translatable::disable() and i18n::disable() - use Object::remove_extension('SiteTree','Translatable'), Deprecated Translatable::enabled() - use $myPage->hasExtension('Translatable') API CHANGE Removed Translatable::creating_from() - doesn't apply any longer ENHANCEMENT Translatable extension is no longer hooked up to SiteTree by default, which should improve performance and memory usage for sites not using Translatable. Please use Object::add_extension('SiteTree','Translatable') in your _config.php instead. Adjusted several classes (Image, ErrorPage, RootURLController) to the new behaviour. ------------------------------------------------------------------------ r73882 | ischommer | 2009-04-01 08:31:21 +1300 (Wed, 01 Apr 2009) | 1 line ENHANCEMENT Added DataObjectDecorator->setOwner() ------------------------------------------------------------------------ r73884 | ischommer | 2009-04-01 08:32:51 +1300 (Wed, 01 Apr 2009) | 1 line ENHANCEMENT Added Extension::get_classname_without_arguments() ------------------------------------------------------------------------ r73900 | ischommer | 2009-04-01 11:27:53 +1300 (Wed, 01 Apr 2009) | 7 lines API CHANGE Deprecated Object->extInstance(), use getExtensionInstance() instead ENHANCEMENT Added Object->getExtensionInstances() ENHANCEMENT Added Object::get_extensions() ENHANCEMENT Unsetting class caches when using Object::add_extension() to avoid problems with defineMethods etc. BUGFIX Fixed extension comparison with case sensitivity and stripping arguments in Object::has_extension() BUGFIX Unsetting all cached singletons in Object::remove_extension() to avoid outdated extension_instances MINOR Documentation in Object ------------------------------------------------------------------------ r74017 | ischommer | 2009-04-03 10:49:40 +1300 (Fri, 03 Apr 2009) | 1 line ENHANCEMENT Improved deprecated fallbacks in Translatable by auto-converting short language codes to long locales and vice versa through i18n::get_lang_from_locale()/i18n::get_locale_from_lang() ------------------------------------------------------------------------ r74030 | ischommer | 2009-04-03 11:41:26 +1300 (Fri, 03 Apr 2009) | 1 line MINOR Re-added Translatable::default_lang() for more graceful fallback to Translatable::default_locale() ------------------------------------------------------------------------ r74065 | ischommer | 2009-04-04 05:38:51 +1300 (Sat, 04 Apr 2009) | 1 line BUGFIX Re-added Translatable->isTranslation() for more friendly deprecation (originally removed in r73338) ------------------------------------------------------------------------ r74069 | ischommer | 2009-04-04 09:43:01 +1300 (Sat, 04 Apr 2009) | 1 line BUGFIX Fixed legacy handling of Translatable::enable(),Translatable::disable() and Translatable::is_enabled() - applying extension to SiteTree instead of Page to avoid datamodel clashes ------------------------------------------------------------------------ r74070 | ischommer | 2009-04-04 10:23:51 +1300 (Sat, 04 Apr 2009) | 1 line API CHANGE Deprecated Translatable::choose_site_lang(), use choose_site_locale() ------------------------------------------------------------------------ r74941 | ischommer | 2009-04-22 15:22:09 +1200 (Wed, 22 Apr 2009) | 2 lines ENHANCEMENT Adding SapphireTest::set_up_once() and SapphireTest::tear_down_once() for better test performance with state that just needs to be initialized once per test case (not per test method). Added new SapphireTestSuite to support this through PHPUnit. ENHANCEMENT Using set_up_once() in TranslatableTest and TranslatableSearchFormTest for better test run performance ------------------------------------------------------------------------ r74942 | ischommer | 2009-04-22 15:24:50 +1200 (Wed, 22 Apr 2009) | 1 line BUGFIX Fixed TranslatableSearchFormTest->setUp() method ------------------------------------------------------------------------ r73509 | ischommer | 2009-03-23 11:59:14 +1300 (Mon, 23 Mar 2009) | 1 line MINOR phpdoc documentation ------------------------------------------------------------------------ git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/branches/2.3@74986 467b73ca-7a2a-4603-9d3b-597d59a354a9
962 lines
30 KiB
PHP
962 lines
30 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Requirements tracker, for javascript and css.
|
|
* @todo Document the requirements tracker, and discuss it with the others.
|
|
* @package sapphire
|
|
* @subpackage view
|
|
*/
|
|
class Requirements {
|
|
|
|
/**
|
|
* Enable combining of css/javascript files.
|
|
*
|
|
* @var boolean
|
|
*/
|
|
private static $combined_files_enabled = true;
|
|
|
|
public static function set_combined_files_enabled($enable) {
|
|
self::$combined_files_enabled = (bool) $enable;
|
|
}
|
|
|
|
public static function get_combined_files_enabled() {
|
|
return self::$combined_files_enabled;
|
|
}
|
|
|
|
/**
|
|
* Do we want requirements to suffix onto the requirement link
|
|
* tags for caching or is it disabled. Getter / Setter available
|
|
* through {@link Requirements::set_suffix_requirements()}
|
|
*
|
|
* @var bool
|
|
*/
|
|
private static $suffix_requirements = true;
|
|
|
|
/**
|
|
* Set whether we want to suffix requirements with the time /
|
|
* location on to the requirements
|
|
*
|
|
* @param bool
|
|
*/
|
|
public static function set_suffix_requirements($var) {
|
|
self::$suffix_requirements = $var;
|
|
}
|
|
|
|
/**
|
|
* Return whether we want to suffix requirements
|
|
*
|
|
* @return bool
|
|
*/
|
|
public static function get_suffix_requirements() {
|
|
return self::$suffix_requirements;
|
|
}
|
|
|
|
/**
|
|
* Instance of requirements for storage
|
|
*
|
|
* @var Requirements
|
|
*/
|
|
private static $backend = null;
|
|
public static function backend() {
|
|
if(!self::$backend) {
|
|
self::$backend = new Requirements_Backend();
|
|
|
|
}
|
|
return self::$backend;
|
|
}
|
|
|
|
/**
|
|
* Setter method for changing the Requirements backend
|
|
*
|
|
* @param Requirements $backend
|
|
*/
|
|
public static function set_backend(Requirements_Backend $backend) {
|
|
self::$backend = $backend;
|
|
}
|
|
|
|
|
|
/**
|
|
* Register the given javascript file as required.
|
|
*
|
|
* See {@link Requirements_Backend::javascript()} for more info
|
|
*
|
|
*/
|
|
static function javascript($file) {
|
|
self::backend()->javascript($file);
|
|
}
|
|
|
|
|
|
/**
|
|
* Add the javascript code to the header of the page
|
|
*
|
|
* See {@link Requirements_Backend::customScript()} for more info
|
|
* @param script The script content
|
|
* @param uniquenessID Use this to ensure that pieces of code only get added once.
|
|
*/
|
|
static function customScript($script, $uniquenessID = null) {
|
|
self::backend()->customScript($script, $uniquenessID);
|
|
}
|
|
|
|
/**
|
|
* Include custom CSS styling to the header of the page.
|
|
*
|
|
* See {@link Requirements_Backend::customCSS()}
|
|
*
|
|
* @param string $script CSS selectors as a string (without <style> tag enclosing selectors).
|
|
* @param int $uniquenessID Group CSS by a unique ID as to avoid duplicate custom CSS in header
|
|
*/
|
|
static function customCSS($script, $uniquenessID = null) {
|
|
self::backend()->customCSS($script, $uniquenessID);
|
|
}
|
|
|
|
/**
|
|
* Add the following custom code to the <head> section of the page.
|
|
* See {@link Requirements_Backend::insertHeadTags()}
|
|
*
|
|
* @param string $html
|
|
* @param string $uniquenessID
|
|
*/
|
|
static function insertHeadTags($html, $uniquenessID = null) {
|
|
self::backend()->insertHeadTags($html, $uniquenessID);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Load the given javascript template with the page.
|
|
* See {@link Requirements_Backend::javascriptTemplate()}
|
|
*
|
|
* @param file The template file to load.
|
|
* @param vars The array of variables to load. These variables are loaded via string search & replace.
|
|
*/
|
|
static function javascriptTemplate($file, $vars, $uniquenessID = null) {
|
|
self::backend()->javascriptTemplate($file, $vars, $uniquenessID);
|
|
}
|
|
|
|
/**
|
|
* Register the given stylesheet file as required.
|
|
* See {@link Requirements_Backend::css()}
|
|
*
|
|
* @param $file String Filenames should be relative to the base, eg, 'jsparty/tree/tree.css'
|
|
* @param $media String Comma-separated list of media-types (e.g. "screen,projector")
|
|
* @see http://www.w3.org/TR/REC-CSS2/media.html
|
|
*/
|
|
static function css($file, $media = null) {
|
|
self::backend()->css($file, $media);
|
|
}
|
|
|
|
/**
|
|
* Register the given "themeable stylesheet" as required. See {@link Requirements_Backend::themedCSS()}
|
|
*
|
|
* @param $name String The identifier of the file. For example, css/MyFile.css would have the identifier "MyFile"
|
|
* @param $media String Comma-separated list of media-types (e.g. "screen,projector")
|
|
*/
|
|
static function themedCSS($name, $media = null) {
|
|
return self::backend()->themedCSS($name, $media);
|
|
}
|
|
|
|
/**
|
|
* Clear either a single or all requirements.
|
|
* Caution: Clearing single rules works only with customCSS and customScript if you specified a {@uniquenessID}.
|
|
*
|
|
* See {@link Requirements_Backend::clear()}
|
|
*
|
|
* @param $file String
|
|
*/
|
|
static function clear($fileOrID = null) {
|
|
self::backend()->clear($fileOrID);
|
|
}
|
|
|
|
/**
|
|
* Blocks inclusion of a specific file
|
|
* See {@link Requirements_Backend::block()}
|
|
*
|
|
* @param unknown_type $fileOrID
|
|
*/
|
|
static function block($fileOrID) {
|
|
self::backend()->block($fileOrID);
|
|
}
|
|
|
|
/**
|
|
* Removes an item from the blocking-list.
|
|
* See {@link Requirements_Backend::unblock()}
|
|
*
|
|
* @param string $fileOrID
|
|
*/
|
|
static function unblock($fileOrID) {
|
|
self::backend()->unblock($fileOrID);
|
|
}
|
|
|
|
/**
|
|
* Removes all items from the blocking-list.
|
|
* See {@link Requirements_Backend::unblock_all()}
|
|
*/
|
|
static function unblock_all() {
|
|
self::backend()->unblock_all();
|
|
}
|
|
|
|
|
|
/**
|
|
* Restore requirements cleared by call to Requirements::clear
|
|
* See {@link Requirements_Backend::restore()}
|
|
*/
|
|
static function restore() {
|
|
self::backend()->restore();
|
|
}
|
|
|
|
/**
|
|
* Update the given HTML content with the appropriate include tags for the registered
|
|
* requirements.
|
|
* See {@link Requirements_Backend::includeInHTML()} for more information.
|
|
*
|
|
* @param string $templateFilePath Absolute path for the *.ss template file
|
|
* @param string $content HTML content that has already been parsed from the $templateFilePath through {@link SSViewer}.
|
|
* @return string HTML content thats augumented with the requirements before the closing <head> tag.
|
|
*/
|
|
static function includeInHTML($templateFile, $content) {
|
|
return self::backend()->includeInHTML($templateFile, $content);
|
|
}
|
|
|
|
static function include_in_response(HTTPResponse $response) {
|
|
return self::backend()->include_in_response($response);
|
|
}
|
|
|
|
/**
|
|
* Add i18n files from the given javascript directory.
|
|
* @param $langDir The javascript lang directory, relative to the site root, e.g., 'sapphire/javascript/lang'
|
|
*
|
|
* See {@link Requirements_Backend::add_i18n_javascript()} for more information.
|
|
*/
|
|
public static function add_i18n_javascript($langDir) {
|
|
return self::backend()->add_i18n_javascript($langDir);
|
|
}
|
|
|
|
/**
|
|
* Concatenate several css or javascript files into a single dynamically generated file.
|
|
* See {@link Requirements_Backend::combine_files()} for more info.
|
|
*
|
|
* @param string $combinedFileName
|
|
* @param array $files
|
|
*/
|
|
static function combine_files($combinedFileName, $files) {
|
|
self::backend()->combine_files($combinedFileName, $files);
|
|
}
|
|
|
|
/**
|
|
* Returns all combined files.
|
|
* See {@link Requirements_Backend::get_combine_files()}
|
|
*
|
|
* @return array
|
|
*/
|
|
static function get_combine_files() {
|
|
return self::backend()->get_combine_files();
|
|
}
|
|
|
|
/**
|
|
* Deletes all dynamically generated combined files from the filesystem.
|
|
* See {@link Requirements_Backend::delete_combine_files()}
|
|
*
|
|
* @param string $combinedFileName If left blank, all combined files are deleted.
|
|
*/
|
|
static function delete_combined_files($combinedFileName = null) {
|
|
return self::backend()->delete_combined_files($combinedFileName);
|
|
}
|
|
|
|
|
|
/**
|
|
* Re-sets the combined files definition. See {@link Requirements_Backend::clear_combined_files()}
|
|
*/
|
|
static function clear_combined_files() {
|
|
self::backend()->clear_combined_files();
|
|
}
|
|
|
|
/**
|
|
* See {@link combine_files()}.
|
|
*/
|
|
static function process_combined_files() {
|
|
return self::backend()->process_combined_files();
|
|
}
|
|
|
|
/**
|
|
* Returns all custom scripts
|
|
* See {@link Requirements_Backend::get_custom_scripts()}
|
|
*
|
|
* @return array
|
|
*/
|
|
static function get_custom_scripts() {
|
|
return self::backend()->get_custom_scripts();
|
|
}
|
|
|
|
/**
|
|
* Set whether you want to write the JS to the body of the page or
|
|
* in the head section
|
|
*
|
|
* @see Requirements_Backend::set_write_js_to_body()
|
|
* @param boolean
|
|
*/
|
|
static function set_write_js_to_body($var) {
|
|
self::backend()->set_write_js_to_body($var);
|
|
}
|
|
|
|
static function debug() {
|
|
return self::backend()->debug();
|
|
}
|
|
|
|
}
|
|
|
|
class Requirements_Backend {
|
|
/**
|
|
* Paths to all required .js files relative to the webroot.
|
|
*
|
|
* @var array $javascript
|
|
*/
|
|
protected $javascript = array();
|
|
|
|
/**
|
|
* Paths to all required .css files relative to the webroot.
|
|
*
|
|
* @var array $css
|
|
*/
|
|
protected $css = array();
|
|
|
|
/**
|
|
* All custom javascript code that is inserted
|
|
* directly at the bottom of the HTML <head> tag.
|
|
*
|
|
* @var array $customScript
|
|
*/
|
|
protected $customScript = array();
|
|
|
|
/**
|
|
* All custom CSS rules which are inserted
|
|
* directly at the bottom of the HTML <head> tag.
|
|
*
|
|
* @var array $customCSS
|
|
*/
|
|
protected $customCSS = array();
|
|
|
|
/**
|
|
* All custom HTML markup which is added before
|
|
* the closing <head> tag, e.g. additional metatags.
|
|
* This is preferred to entering tags directly into
|
|
*/
|
|
protected $customHeadTags = array();
|
|
|
|
/**
|
|
* Remembers the filepaths of all cleared Requirements
|
|
* through {@link clear()}.
|
|
*
|
|
* @var array $disabled
|
|
*/
|
|
protected $disabled = array();
|
|
|
|
/**
|
|
* The filepaths (relative to webroot) or
|
|
* uniquenessIDs of any included requirements
|
|
* which should be blocked when executing {@link inlcudeInHTML()}.
|
|
* This is useful to e.g. prevent core classes to modifying
|
|
* Requirements without subclassing the entire functionality.
|
|
* Use {@link unblock()} or {@link unblock_all()} to revert changes.
|
|
*
|
|
* @var array $blocked
|
|
*/
|
|
protected $blocked = array();
|
|
|
|
/**
|
|
* See {@link combine_files()}.
|
|
*
|
|
* @var array $combine_files
|
|
*/
|
|
public $combine_files = array();
|
|
|
|
/**
|
|
* Using the JSMin library to minify any
|
|
* javascript file passed to {@link combine_files()}.
|
|
*
|
|
* @var boolean
|
|
*/
|
|
public $combine_js_with_jsmin = true;
|
|
|
|
/**
|
|
* Put all javascript includes at the bottom of the template
|
|
* before the closing <body> tag instead of the <head> tag.
|
|
* This means script downloads won't block other HTTP-requests,
|
|
* which can be a performance improvement.
|
|
* Caution: Doesn't work when modifying the DOM from those external
|
|
* scripts without listening to window.onload/document.ready
|
|
* (e.g. toplevel document.write() calls).
|
|
*
|
|
* @see http://developer.yahoo.com/performance/rules.html#js_bottom
|
|
*
|
|
* @var boolean
|
|
*/
|
|
public $write_js_to_body = true;
|
|
|
|
/**
|
|
* Set whether you want the files written to the head or the body. It
|
|
* writes to the body by default which can break some scripts
|
|
*
|
|
* @param boolean
|
|
*/
|
|
public function set_write_js_to_body($var) {
|
|
$this->write_js_to_body = $var;
|
|
}
|
|
/**
|
|
* Register the given javascript file as required.
|
|
* Filenames should be relative to the base, eg, 'sapphire/javascript/loader.js'
|
|
*/
|
|
|
|
public function javascript($file) {
|
|
$this->javascript[$file] = true;
|
|
}
|
|
|
|
/**
|
|
* Returns an array of all included javascript
|
|
*
|
|
* @return array
|
|
*/
|
|
public function get_javascript() {
|
|
return array_keys(array_diff_key($this->javascript,$this->blocked));
|
|
}
|
|
|
|
/**
|
|
* Add the javascript code to the header of the page
|
|
* @todo Make Requirements automatically put this into a separate file :-)
|
|
* @param script The script content
|
|
* @param uniquenessID Use this to ensure that pieces of code only get added once.
|
|
*/
|
|
public function customScript($script, $uniquenessID = null) {
|
|
if($uniquenessID)
|
|
$this->customScript[$uniquenessID] = $script;
|
|
else {
|
|
$this->customScript[] = $script;
|
|
}
|
|
$script .= "\n";
|
|
}
|
|
|
|
/**
|
|
* Include custom CSS styling to the header of the page.
|
|
*
|
|
* @param string $script CSS selectors as a string (without <style> tag enclosing selectors).
|
|
* @param int $uniquenessID Group CSS by a unique ID as to avoid duplicate custom CSS in header
|
|
*/
|
|
function customCSS($script, $uniquenessID = null) {
|
|
if($uniquenessID)
|
|
$this->customCSS[$uniquenessID] = $script;
|
|
else {
|
|
$this->customCSS[] = $script;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add the following custom code to the <head> section of the page.
|
|
*
|
|
* @param string $html
|
|
* @param string $uniquenessID
|
|
*/
|
|
function insertHeadTags($html, $uniquenessID = null) {
|
|
if($uniquenessID)
|
|
$this->customHeadTags[$uniquenessID] = $html;
|
|
else {
|
|
$this->customHeadTags[] = $html;
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Load the given javascript template with the page.
|
|
* @param file The template file to load.
|
|
* @param vars The array of variables to load. These variables are loaded via string search & replace.
|
|
*/
|
|
function javascriptTemplate($file, $vars, $uniquenessID = null) {
|
|
$script = file_get_contents(Director::getAbsFile($file));
|
|
foreach($vars as $k => $v) {
|
|
$search[] = '$' . $k;
|
|
$replace[] = str_replace("\\'","'", Convert::raw2js($v));
|
|
}
|
|
$script = str_replace($search, $replace, $script);
|
|
$this->customScript($script, $uniquenessID);
|
|
}
|
|
|
|
/**
|
|
* Register the given stylesheet file as required.
|
|
*
|
|
* @param $file String Filenames should be relative to the base, eg, 'jsparty/tree/tree.css'
|
|
* @param $media String Comma-separated list of media-types (e.g. "screen,projector")
|
|
* @see http://www.w3.org/TR/REC-CSS2/media.html
|
|
*/
|
|
function css($file, $media = null) {
|
|
$this->css[$file] = array(
|
|
"media" => $media
|
|
);
|
|
}
|
|
|
|
function get_css() {
|
|
return array_diff_key($this->css, $this->blocked);
|
|
}
|
|
|
|
/**
|
|
* Needed to actively prevent the inclusion of a file,
|
|
* e.g. when using your own prototype.js.
|
|
* Blocking should only be used as an exception, because
|
|
* it is hard to trace back. You can just block items with an
|
|
* ID, so make sure you add an unique identifier to customCSS() and customScript().
|
|
*
|
|
* @param string $fileOrID
|
|
*/
|
|
function block($fileOrID) {
|
|
$this->blocked[$fileOrID] = $fileOrID;
|
|
}
|
|
|
|
/**
|
|
* Clear either a single or all requirements.
|
|
* Caution: Clearing single rules works only with customCSS and customScript if you specified a {@uniquenessID}.
|
|
*
|
|
* @param $file String
|
|
*/
|
|
function clear($fileOrID = null) {
|
|
if($fileOrID) {
|
|
foreach(array('javascript','css', 'customScript', 'customCSS') as $type) {
|
|
if(isset($this->{$type}[$fileOrID])) {
|
|
$this->disabled[$type][$fileOrID] = $this->{$type}[$fileOrID];
|
|
unset($this->{$type}[$fileOrID]);
|
|
}
|
|
}
|
|
} else {
|
|
$this->disabled['javascript'] = $this->javascript;
|
|
$this->disabled['css'] = $this->css;
|
|
$this->disabled['customScript'] = $this->customScript;
|
|
$this->disabled['customCSS'] = $this->customCSS;
|
|
$this->disabled['customHeadTags'] = $this->customHeadTags;
|
|
|
|
$this->javascript = array();
|
|
$this->css = array();
|
|
$this->customScript = array();
|
|
$this->customCSS = array();
|
|
$this->customHeadTags = array();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Removes an item from the blocking-list.
|
|
* CAUTION: Does not "re-add" any previously blocked elements.
|
|
* @param string $fileOrID
|
|
*/
|
|
function unblock($fileOrID) {
|
|
if(isset($this->blocked[$fileOrID])) unset($this->blocked[$fileOrID]);
|
|
}
|
|
/**
|
|
* Removes all items from the blocking-list.
|
|
*/
|
|
function unblock_all() {
|
|
$this->blocked = array();
|
|
}
|
|
|
|
/**
|
|
* Restore requirements cleared by call to Requirements::clear
|
|
*/
|
|
function restore() {
|
|
$this->javascript = $this->disabled['javascript'];
|
|
$this->css = $this->disabled['css'];
|
|
$this->customScript = $this->disabled['customScript'];
|
|
$this->customCSS = $this->disabled['customCSS'];
|
|
$this->customHeadTags = $this->disabled['customHeadTags'];
|
|
}
|
|
|
|
/**
|
|
* Update the given HTML content with the appropriate include tags for the registered
|
|
* requirements. Needs to receive a valid HTML/XHTML template in the $content parameter,
|
|
* including a <head> tag. The requirements will insert before the closing <head> tag automatically.
|
|
*
|
|
* @todo Calculate $prefix properly
|
|
*
|
|
* @param string $templateFilePath Absolute path for the *.ss template file
|
|
* @param string $content HTML content that has already been parsed from the $templateFilePath through {@link SSViewer}.
|
|
* @return string HTML content thats augumented with the requirements before the closing <head> tag.
|
|
*/
|
|
function includeInHTML($templateFile, $content) {
|
|
if(isset($_GET['debug_profile'])) Profiler::mark("Requirements::includeInHTML");
|
|
|
|
if(strpos($content, '</head') !== false && ($this->css || $this->javascript || $this->customCSS || $this->customScript || $this->customHeadTags)) {
|
|
$requirements = '';
|
|
$jsRequirements = '';
|
|
|
|
// Combine files - updates $this->javascript and $this->css
|
|
$this->process_combined_files();
|
|
|
|
foreach(array_diff_key($this->javascript,$this->blocked) as $file => $dummy) {
|
|
$path = self::path_for_file($file);
|
|
if($path) {
|
|
$jsRequirements .= "<script type=\"text/javascript\" src=\"$path\"></script>\n";
|
|
}
|
|
}
|
|
|
|
// add all inline javascript *after* including external files which
|
|
// they might rely on
|
|
if($this->customScript) {
|
|
foreach(array_diff_key($this->customScript,$this->blocked) as $script) {
|
|
$jsRequirements .= "<script type=\"text/javascript\">\n//<![CDATA[\n";
|
|
$jsRequirements .= "$script\n";
|
|
$jsRequirements .= "\n//]]>\n</script>\n";
|
|
}
|
|
}
|
|
|
|
foreach(array_diff_key($this->css,$this->blocked) as $file => $params) {
|
|
$path = self::path_for_file($file);
|
|
if($path) {
|
|
$media = (isset($params['media']) && !empty($params['media'])) ? " media=\"{$params['media']}\"" : "";
|
|
$requirements .= "<link rel=\"stylesheet\" type=\"text/css\"{$media} href=\"$path\" />\n";
|
|
}
|
|
}
|
|
foreach(array_diff_key($this->customCSS, $this->blocked) as $css) {
|
|
$requirements .= "<style type=\"text/css\">\n$css\n</style>\n";
|
|
}
|
|
foreach(array_diff_key($this->customHeadTags,$this->blocked) as $customHeadTag) {
|
|
$requirements .= "$customHeadTag\n";
|
|
}
|
|
|
|
if($this->write_js_to_body) {
|
|
// Remove all newlines from code to preserve layout
|
|
$jsRequirements = preg_replace('/>\n*/', '>', $jsRequirements);
|
|
|
|
// We put script tags into the body, for performance.
|
|
// If your template already has script tags in the body, then we put our script tags at the top of the body.
|
|
// Otherwise, we put it at the bottom.
|
|
$p1 = strripos($content, '<script');
|
|
$p2 = stripos($content, '<body');
|
|
if($p1 !== false && $p1 > $p2) {
|
|
user_error("You have a script tag in the body, moving requirements to top of <body> for compatibilty. I recommend removing the script tag from your template's body.", E_USER_NOTICE);
|
|
$content = eregi_replace("(<body[^>]*>)", "\\1" . $jsRequirements, $content);
|
|
} else {
|
|
$content = eregi_replace("(</body[^>]*>)", $jsRequirements . "\\1", $content);
|
|
}
|
|
|
|
// Put CSS at the bottom of the head
|
|
$content = eregi_replace("(</head[^>]*>)", $requirements . "\\1", $content);
|
|
} else {
|
|
$content = eregi_replace("(</head[^>]*>)", $requirements . "\\1", $content);
|
|
$content = eregi_replace("(</head[^>]*>)", $jsRequirements . "\\1", $content);
|
|
}
|
|
}
|
|
|
|
if(isset($_GET['debug_profile'])) Profiler::unmark("Requirements::includeInHTML");
|
|
|
|
return $content;
|
|
}
|
|
|
|
/**
|
|
* Attach requirements inclusion to X-Include-JS and X-Include-CSS headers on the HTTP response
|
|
*/
|
|
function include_in_response(HTTPResponse $response) {
|
|
$this->process_combined_files();
|
|
$jsRequirements = array();
|
|
$cssRequirements = array();
|
|
|
|
foreach(array_diff_key($this->javascript, $this->blocked) as $file => $dummy) {
|
|
$path = $this->path_for_file($file);
|
|
if($path) $jsRequirements[] = $path;
|
|
}
|
|
|
|
$response->addHeader('X-Include-JS', implode(',', $jsRequirements));
|
|
|
|
foreach(array_diff_key($this->css,$this->blocked) as $file => $params) {
|
|
$path = $this->path_for_file($file);
|
|
if($path) $cssRequirements[] = isset($params['media']) ? "$path:##:$params[media]" : $path;
|
|
}
|
|
|
|
$response->addHeader('X-Include-CSS', implode(',', $cssRequirements));
|
|
}
|
|
|
|
/**
|
|
* Add i18n files from the given javascript directory. Sapphire expects that the given directory
|
|
* will contain a number of java script files named by language: en_US.js, de_DE.js, etc.
|
|
* @param $langDir The javascript lang directory, relative to the site root, e.g., 'sapphire/javascript/lang'
|
|
*/
|
|
public function add_i18n_javascript($langDir) {
|
|
if(i18n::get_js_i18n()) {
|
|
// Include i18n.js even if no languages are found. The fact that
|
|
// add_i18n_javascript() was called indicates that the methods in
|
|
// here are needed.
|
|
$this->javascript(SAPPHIRE_DIR . '/javascript/i18n.js');
|
|
|
|
if(substr($langDir,-1) != '/') $langDir .= '/';
|
|
|
|
$this->javascript($langDir . i18n::default_locale() . '.js');
|
|
$this->javascript($langDir . i18n::get_locale() . '.js');
|
|
|
|
// Stub i18n implementation for when i18n is disabled.
|
|
} else {
|
|
$this->javascript[SAPPHIRE_DIR . '/javascript/i18nx.js'] = true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Finds the path for specified file.
|
|
*
|
|
* @param string $fileOrUrl
|
|
* @return string|boolean
|
|
*/
|
|
protected static function path_for_file($fileOrUrl) {
|
|
if(preg_match('/^http[s]?/', $fileOrUrl)) {
|
|
return $fileOrUrl;
|
|
} elseif(Director::fileExists($fileOrUrl)) {
|
|
$prefix = Director::absoluteBaseURL();
|
|
$mtimesuffix = "";
|
|
$suffix = '';
|
|
if(strpos($fileOrUrl, '?') !== false) {
|
|
$suffix = '&' . substr($fileOrUrl, strpos($fileOrUrl, '?')+1);
|
|
$fileOrUrl = substr($fileOrUrl, 0, strpos($fileOrUrl, '?'));
|
|
}
|
|
if(Requirements::get_suffix_requirements()) {
|
|
$mtimesuffix = "?m=" . filemtime(Director::baseFolder() . '/' . $fileOrUrl);
|
|
}
|
|
return "{$prefix}{$fileOrUrl}{$mtimesuffix}{$suffix}";
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Concatenate several css or javascript files into a single dynamically generated
|
|
* file (stored in {@link Director::baseFolder()}). This increases performance
|
|
* by fewer HTTP requests.
|
|
*
|
|
* The combined file is regenerated
|
|
* based on every file modification time. Optionally a rebuild can be triggered
|
|
* by appending ?flush=1 to the URL.
|
|
* If all files to be combined are javascript, we use the external JSMin library
|
|
* to minify the javascript. This can be controlled by {@link $combine_js_with_jsmin}.
|
|
*
|
|
* All combined files will have a comment on the start of each concatenated file
|
|
* denoting their original position. For easier debugging, we recommend to only
|
|
* minify javascript if not in development mode ({@link Director::isDev()}).
|
|
*
|
|
* CAUTION: You're responsible for ensuring that the load order for combined files
|
|
* is retained - otherwise combining javascript files can lead to functional errors
|
|
* in the javascript logic, and combining css can lead to wrong styling inheritance.
|
|
* Depending on the javascript logic, you also have to ensure that files are not included
|
|
* in more than one combine_files() call.
|
|
* Best practice is to include every javascript file in exactly *one* combine_files()
|
|
* directive to avoid the issues mentioned above - this is enforced by this function.
|
|
*
|
|
* CAUTION: Combining CSS Files discards any "media" information.
|
|
*
|
|
* Example for combined JavaScript:
|
|
* <code>
|
|
* Requirements::combine_files(
|
|
* 'foobar.js',
|
|
* array(
|
|
* 'mysite/javascript/foo.js',
|
|
* 'mysite/javascript/bar.js',
|
|
* )
|
|
* );
|
|
* </code>
|
|
*
|
|
* Example for combined CSS:
|
|
* <code>
|
|
* Requirements::combine_files(
|
|
* 'foobar.css',
|
|
* array(
|
|
* 'mysite/javascript/foo.css',
|
|
* 'mysite/javascript/bar.css',
|
|
* )
|
|
* );
|
|
* </code>
|
|
*
|
|
* @see http://code.google.com/p/jsmin-php/
|
|
*
|
|
* @todo Should we enforce unique inclusion of files, or leave it to the developer? Can auto-detection cause breaks?
|
|
*
|
|
* @param string $combinedFileName Filename of the combined file (will be stored in {@link Director::baseFolder()} by default)
|
|
* @param array $files Array of filenames relative to the webroot
|
|
*/
|
|
function combine_files($combinedFileName, $files) {
|
|
// duplicate check
|
|
foreach($this->combine_files as $_combinedFileName => $_files) {
|
|
$duplicates = array_intersect($_files, $files);
|
|
if($duplicates) {
|
|
user_error("Requirements::combine_files(): Already included files " . implode(',', $duplicates) . " in combined file '{$_combinedFileName}'", E_USER_NOTICE);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
$this->combine_files[$combinedFileName] = $files;
|
|
}
|
|
|
|
/**
|
|
* Returns all combined files.
|
|
* @return array
|
|
*/
|
|
function get_combine_files() {
|
|
return $this->combine_files;
|
|
}
|
|
|
|
/**
|
|
* Deletes all dynamically generated combined files from the filesystem.
|
|
*
|
|
* @param string $combinedFileName If left blank, all combined files are deleted.
|
|
*/
|
|
function delete_combined_files($combinedFileName = null) {
|
|
$combinedFiles = ($combinedFileName) ? array($combinedFileName => null) : $this->combine_files;
|
|
foreach($combinedFiles as $combinedFile => $sourceItems) {
|
|
$filePath = Director::baseFolder() . '/' . $combinedFile;
|
|
if(file_exists($filePath)) {
|
|
unlink($filePath);
|
|
}
|
|
}
|
|
}
|
|
|
|
function clear_combined_files() {
|
|
$this->combine_files = array();
|
|
}
|
|
|
|
|
|
/**
|
|
* See {@link combine_files()}
|
|
*
|
|
*/
|
|
function process_combined_files() {
|
|
|
|
if((Director::isDev() && !SapphireTest::is_running_test()) || !Requirements::get_combined_files_enabled()) {
|
|
return;
|
|
}
|
|
|
|
// Make a map of files that could be potentially combined
|
|
$combinerCheck = array();
|
|
foreach($this->combine_files as $combinedFile => $sourceItems) {
|
|
foreach($sourceItems as $sourceItem) {
|
|
if(isset($combinerCheck[$sourceItem]) && $combinerCheck[$sourceItem] != $combinedFile){
|
|
user_error("Requirements::process_combined_files - file '$sourceItem' appears in two combined files:" . " '{$combinerCheck[$sourceItem]}' and '$combinedFile'", E_USER_WARNING);
|
|
}
|
|
$combinerCheck[$sourceItem] = $combinedFile;
|
|
|
|
}
|
|
}
|
|
|
|
// Figure out which ones apply to this pageview
|
|
$combinedFiles = array();
|
|
$newJSRequirements = array();
|
|
$newCSSRequirements = array();
|
|
foreach($this->javascript as $file => $dummy) {
|
|
if(isset($combinerCheck[$file])) {
|
|
$newJSRequirements[$combinerCheck[$file]] = true;
|
|
$combinedFiles[$combinerCheck[$file]] = true;
|
|
} else {
|
|
$newJSRequirements[$file] = true;
|
|
}
|
|
}
|
|
|
|
foreach($this->css as $file => $params) {
|
|
if(isset($combinerCheck[$file])) {
|
|
$newCSSRequirements[$combinerCheck[$file]] = true;
|
|
$combinedFiles[$combinerCheck[$file]] = true;
|
|
} else {
|
|
$newCSSRequirements[$file] = $params;
|
|
}
|
|
}
|
|
|
|
// Process the combined files
|
|
$base = Director::baseFolder() . '/';
|
|
foreach(array_diff_key($combinedFiles,$this->blocked) as $combinedFile => $dummy) {
|
|
$fileList = $this->combine_files[$combinedFile];
|
|
|
|
// Determine if we need to build the combined include
|
|
if(file_exists($base . $combinedFile) && !isset($_GET['flush'])) {
|
|
// file exists, check modification date of every contained file
|
|
$srcLastMod = 0;
|
|
foreach($fileList as $file) {
|
|
$srcLastMod = max(filemtime($base . $file), $srcLastMod);
|
|
}
|
|
$refresh = $srcLastMod > filemtime($base . $combinedFile);
|
|
} else {
|
|
// file doesn't exist, or refresh was explicitly required
|
|
$refresh = true;
|
|
}
|
|
|
|
if(!$refresh) continue;
|
|
|
|
$combinedData = "";
|
|
foreach(array_diff($fileList,$this->blocked) as $file) {
|
|
$fileContent = file_get_contents($base . $file);
|
|
// if we have a javascript file and jsmin is enabled, minify the content
|
|
if(stripos($file, '.js') && $this->combine_js_with_jsmin) {
|
|
require_once('thirdparty/jsmin/JSMin.php');
|
|
|
|
set_time_limit(0);
|
|
$fileContent = JSMin::minify($fileContent);
|
|
}
|
|
// write a header comment for each file for easier identification and debugging
|
|
$combinedData .= "/****** FILE: $file *****/\n" . $fileContent . "\n;\n";
|
|
}
|
|
if(!file_exists(dirname($base . $combinedFile))) {
|
|
Filesystem::makeFolder(dirname($base . $combinedFile));
|
|
}
|
|
|
|
$successfulWrite = false;
|
|
$fh = fopen($base . $combinedFile, 'w');
|
|
if($fh) {
|
|
if(fwrite($fh, $combinedData) == strlen($combinedData)) $successfulWrite = true;
|
|
fclose($fh);
|
|
unset($fh);
|
|
}
|
|
|
|
// Unsuccessful write - just include the regular JS files, rather than the combined one
|
|
if(!$successfulWrite) {
|
|
user_error("Requirements_Backend::process_combined_files(): Couldn't create '$base$combinedFile'", E_USER_WARNING);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// @todo Alters the original information, which means you can't call this
|
|
// method repeatedly - it will behave different on the second call!
|
|
$this->javascript = $newJSRequirements;
|
|
$this->css = $newCSSRequirements;
|
|
}
|
|
|
|
function get_custom_scripts() {
|
|
$requirements = "";
|
|
|
|
if($this->customScript) {
|
|
foreach($this->customScript as $script) {
|
|
$requirements .= "$script\n";
|
|
}
|
|
}
|
|
|
|
return $requirements;
|
|
}
|
|
|
|
/**
|
|
* Register the given "themeable stylesheet" as required.
|
|
* Themeable stylesheets have globally unique names, just like templates and PHP files.
|
|
* Because of this, they can be replaced by similarly named CSS files in the theme directory.
|
|
*
|
|
* @param $name String The identifier of the file. For example, css/MyFile.css would have the identifier "MyFile"
|
|
* @param $media String Comma-separated list of media-types (e.g. "screen,projector")
|
|
*/
|
|
function themedCSS($name, $media = null) {
|
|
global $_CSS_MANIFEST;
|
|
|
|
$theme = SSViewer::current_theme();
|
|
|
|
if($theme && isset($_CSS_MANIFEST[$name]) && isset($_CSS_MANIFEST[$name]['themes'])
|
|
&& isset($_CSS_MANIFEST[$name]['themes'][$theme]))
|
|
Requirements::css($_CSS_MANIFEST[$name]['themes'][$theme], $media);
|
|
|
|
else if(isset($_CSS_MANIFEST[$name]) && isset($_CSS_MANIFEST[$name]['unthemed'])) $this->css($_CSS_MANIFEST[$name]['unthemed'], $media);
|
|
// Normal requirements fails quietly when there is no css - we should do the same
|
|
// else user_error("themedCSS - No CSS file '$name.css' found.", E_USER_WARNING);
|
|
}
|
|
|
|
function debug() {
|
|
Debug::show($this->javascript);
|
|
Debug::show($this->css);
|
|
Debug::show($this->customCSS);
|
|
Debug::show($this->customScript);
|
|
Debug::show($this->customHeadTags);
|
|
Debug::show($this->combine_files);
|
|
}
|
|
|
|
}
|
|
|
|
?>
|