mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
API CHANGE: Removed manifest's dependency on database, by removing hastable information [17:47:04]
dquote> API CHANGE: Deprecate ClassInfo::ready() in favour of Security::database_is_ready() dquote> API CHANGE: Create DataObject::has_own_table() to determine whether a DataObject has a table without looking at it. dquote> API CHANGE: Exclude /tests/ directories from the manifest entirely except when tests are being run. dquote> API CHANGE: Added ?usetestmanifest=1 flag to access the test manifest outside of test execution. dquote> API CHANGE: Simplified Core.php manifest include to just call ManifestBuilder::include_manifest() - manifest takes care of its own cache file git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@65385 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
parent
728e691a1a
commit
c1d6e82248
@ -11,10 +11,6 @@ abstract class CliController extends Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function index() {
|
function index() {
|
||||||
// Always re-compile the manifest (?flush=1)
|
|
||||||
ManifestBuilder::update_db_tables(DB::getConn()->tableList(), $_ALL_CLASSES);
|
|
||||||
ManifestBuilder::write_manifest();
|
|
||||||
|
|
||||||
foreach( ClassInfo::subclassesFor( $this->class ) as $subclass ) {
|
foreach( ClassInfo::subclassesFor( $this->class ) as $subclass ) {
|
||||||
echo $subclass;
|
echo $subclass;
|
||||||
|
|
||||||
|
@ -8,14 +8,6 @@
|
|||||||
* @subpackage core
|
* @subpackage core
|
||||||
*/
|
*/
|
||||||
class ClassInfo {
|
class ClassInfo {
|
||||||
/**
|
|
||||||
* Returns true if the manifest has actually been built.
|
|
||||||
*/
|
|
||||||
static function ready() {
|
|
||||||
global $_ALL_CLASSES;
|
|
||||||
return $_ALL_CLASSES && $_ALL_CLASSES['hastable'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @todo Improve documentation
|
* @todo Improve documentation
|
||||||
*/
|
*/
|
||||||
@ -33,11 +25,11 @@ class ClassInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @todo Improve documentation
|
* @todo Move this to Database or DB
|
||||||
*/
|
*/
|
||||||
static function hasTable($class) {
|
static function hasTable($class) {
|
||||||
global $_ALL_CLASSES;
|
$SQL_table = Convert::raw2sql($class);
|
||||||
return isset($_ALL_CLASSES['hastable'][$class]) ? $_ALL_CLASSES['hastable'][$class] : null;
|
return (bool)(DB::query("SHOW TABLES LIKE '$SQL_table'")->value());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -60,6 +52,7 @@ class ClassInfo {
|
|||||||
* to those with DB tables
|
* to those with DB tables
|
||||||
*
|
*
|
||||||
* @param mixed $class string of the classname or instance of the class
|
* @param mixed $class string of the classname or instance of the class
|
||||||
|
* @todo Move this into data object
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
static function dataClassesFor($class) {
|
static function dataClassesFor($class) {
|
||||||
@ -70,20 +63,15 @@ class ClassInfo {
|
|||||||
|
|
||||||
if(!$_ALL_CLASSES['parents'][$class]) user_error("ClassInfo::dataClassesFor() no parents for $class", E_USER_WARNING);
|
if(!$_ALL_CLASSES['parents'][$class]) user_error("ClassInfo::dataClassesFor() no parents for $class", E_USER_WARNING);
|
||||||
foreach($_ALL_CLASSES['parents'][$class] as $subclass) {
|
foreach($_ALL_CLASSES['parents'][$class] as $subclass) {
|
||||||
if(isset($_ALL_CLASSES['hastable'][$subclass])){
|
if(DataObject::has_own_table($subclass)) $dataClasses[] = $subclass;
|
||||||
$dataClasses[] = $subclass;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isset($_ALL_CLASSES['hastable'][$class])) $dataClasses[] = $class;
|
if(DataObject::has_own_table($class)) $dataClasses[] = $class;
|
||||||
|
|
||||||
if(isset($_ALL_CLASSES['children'][$class]))
|
if(isset($_ALL_CLASSES['children'][$class]))
|
||||||
foreach($_ALL_CLASSES['children'][$class] as $subclass)
|
foreach($_ALL_CLASSES['children'][$class] as $subclass)
|
||||||
{
|
{
|
||||||
if(isset($_ALL_CLASSES['hastable'][$subclass]))
|
if(DataObject::has_own_table($subclass)) $dataClasses[] = $subclass;
|
||||||
{
|
|
||||||
$dataClasses[] = $subclass;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $dataClasses;
|
return $dataClasses;
|
||||||
@ -134,7 +122,7 @@ class ClassInfo {
|
|||||||
$items = $_ALL_CLASSES['parents'][$class];
|
$items = $_ALL_CLASSES['parents'][$class];
|
||||||
$items[$class] = $class;
|
$items[$class] = $class;
|
||||||
if($onlyWithTables) foreach($items as $item) {
|
if($onlyWithTables) foreach($items as $item) {
|
||||||
if(!isset($_ALL_CLASSES['hastable'][$item]) || !$_ALL_CLASSES['hastable'][$item]) unset($items[$item]);
|
if(!DataObject::has_own_table($item)) unset($items[$item]);
|
||||||
}
|
}
|
||||||
return $items;
|
return $items;
|
||||||
}
|
}
|
||||||
@ -174,5 +162,17 @@ class ClassInfo {
|
|||||||
|
|
||||||
return $matchedClasses;
|
return $matchedClasses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// DEPRECATED
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use Security::database_is_ready() instead.
|
||||||
|
*/
|
||||||
|
static function ready() {
|
||||||
|
user_error("ClassInfo::ready() deprectaed - use Security::database_is_ready()", E_USER_NOTICE);
|
||||||
|
return Security::database_is_ready();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
?>
|
?>
|
@ -158,13 +158,9 @@ require_once("core/Session.php");
|
|||||||
// MANIFEST
|
// MANIFEST
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build the manifest
|
* Include the manifest
|
||||||
*/
|
*/
|
||||||
if(ManifestBuilder::staleManifest()){
|
ManifestBuilder::include_manifest();
|
||||||
ManifestBuilder::compileManifest();
|
|
||||||
}
|
|
||||||
|
|
||||||
require_once(MANIFEST_FILE);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ?debugmanifest=1 hook
|
* ?debugmanifest=1 hook
|
||||||
|
@ -41,7 +41,7 @@ class ManifestBuilder {
|
|||||||
'install.php',
|
'install.php',
|
||||||
'index.php',
|
'index.php',
|
||||||
'check-php.php',
|
'check-php.php',
|
||||||
'rewritetest.php'
|
'rewritetest.php',
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -56,54 +56,44 @@ class ManifestBuilder {
|
|||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var int $cache_expiry_mins Specifies the time (in minutes) until a rebuild
|
* Include the manifest, regenerating it if necessary
|
||||||
* of the manifest cache is forced.
|
|
||||||
* @usedby self::staleManifest()
|
|
||||||
*/
|
*/
|
||||||
public static $cache_expiry_mins = 60;
|
static function include_manifest() {
|
||||||
|
if(isset($_REQUEST['usetestmanifest'])) {
|
||||||
/**
|
self::load_test_manifest();
|
||||||
* Returns true if the manifest file should be regenerated,
|
} else {
|
||||||
* by asserting one of the following conditions:
|
if(!file_exists(MANIFEST_FILE) || (filemtime(MANIFEST_FILE) < filemtime(BASE_PATH)) || isset($_GET['flush'])) {
|
||||||
* - Manifest cache file doesn't exist
|
self::create_manifest_file();
|
||||||
* - The modification time of the webroot folder is newer than the cache file
|
}
|
||||||
* - The cache file is older than {@link self::$cache_expiry_mins}
|
require_once(MANIFEST_FILE);
|
||||||
* - A cache rebuild is forced by the "?flush=1" URL parameter
|
}
|
||||||
*
|
|
||||||
* Checked on every request handled by SilverStripe in main.php or cli-script.php.
|
|
||||||
*
|
|
||||||
* @return bool Returns TRUE if the manifest file should be regenerated, otherwise FALSE.
|
|
||||||
*/
|
|
||||||
static function staleManifest() {
|
|
||||||
$lastEdited = filemtime(BASE_PATH);
|
|
||||||
|
|
||||||
return (
|
|
||||||
!file_exists(MANIFEST_FILE)
|
|
||||||
|| (filemtime(MANIFEST_FILE) < $lastEdited)
|
|
||||||
|| (filemtime(MANIFEST_FILE) < time() - 60 * self::$cache_expiry_mins)
|
|
||||||
|| isset($_GET['flush'])
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a copy of the manifest with tests/ folders included.
|
||||||
|
* Only loads the ClassInfo and __autoload() globals; this assumes that _config.php files are already included.
|
||||||
|
*/
|
||||||
|
static function load_test_manifest() {
|
||||||
|
// Build the complete manifest
|
||||||
|
$manifestInfo = self::get_manifest_info(BASE_PATH);
|
||||||
|
// Load it into the current session.
|
||||||
|
self::process_manifest($manifestInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads all PHP class files - actually opening them and executing them.
|
||||||
|
*/
|
||||||
|
static function load_all_classes() {
|
||||||
|
global $_CLASS_MANIFEST;
|
||||||
|
foreach($_CLASS_MANIFEST as $classFile) require_once($classFile);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a new manifest file and saves it to {@link MANIFEST_FILE}.
|
* Generates a new manifest file and saves it to {@link MANIFEST_FILE}.
|
||||||
*/
|
*/
|
||||||
static function compileManifest() {
|
private static function create_manifest_file() {
|
||||||
// Config manifest
|
// Build the manifest, ignoring the tests/ folders
|
||||||
$baseDir = dirname($_SERVER['SCRIPT_FILENAME']) . "/..";
|
$manifestInfo = self::get_manifest_info(BASE_PATH, array("tests"));
|
||||||
$baseDir = ereg_replace("/[^/]+/\\.\\.", "", $baseDir);
|
|
||||||
$baseDir = preg_replace("/\\\\/", "/", $baseDir);
|
|
||||||
|
|
||||||
$manifestInfo = self::get_manifest_info($baseDir);
|
|
||||||
|
|
||||||
// Connect to the database and get the database config
|
|
||||||
global $databaseConfig;
|
|
||||||
DB::connect($databaseConfig);
|
|
||||||
if(DB::isActive()) {
|
|
||||||
$tableList = DB::getConn()->tableList();
|
|
||||||
self::update_db_tables($tableList, $manifestInfo['globals']['_ALL_CLASSES']);
|
|
||||||
}
|
|
||||||
|
|
||||||
$manifest = self::generate_php_file($manifestInfo);
|
$manifest = self::generate_php_file($manifestInfo);
|
||||||
if($fh = fopen(MANIFEST_FILE, "w")) {
|
if($fh = fopen(MANIFEST_FILE, "w")) {
|
||||||
@ -122,7 +112,7 @@ class ManifestBuilder {
|
|||||||
$output = "<?php\n";
|
$output = "<?php\n";
|
||||||
|
|
||||||
foreach($manifestInfo['globals'] as $globalName => $globalVal) {
|
foreach($manifestInfo['globals'] as $globalName => $globalVal) {
|
||||||
$output .= "\$$globalName = " . var_export($globalVal, true) . ";\n\n";
|
$output .= "global \$$globalName;\n\$$globalName = " . var_export($globalVal, true) . ";\n\n";
|
||||||
}
|
}
|
||||||
foreach($manifestInfo['require_once'] as $requireItem) {
|
foreach($manifestInfo['require_once'] as $requireItem) {
|
||||||
$output .= "require_once(\"$requireItem\");\n";
|
$output .= "require_once(\"$requireItem\");\n";
|
||||||
@ -131,11 +121,27 @@ class ManifestBuilder {
|
|||||||
return $output;
|
return $output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the $manifestInfo array, updating the appropriate globals and loading the appropriate _config files.
|
||||||
|
*/
|
||||||
|
static function process_manifest($manifestInfo) {
|
||||||
|
foreach($manifestInfo['globals'] as $globalName => $globalVal) {
|
||||||
|
global $$globalName;
|
||||||
|
$$globalName = $globalVal;
|
||||||
|
}
|
||||||
|
foreach($manifestInfo['require_once'] as $requireItem) {
|
||||||
|
require_once("$requireItem");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an array containing information for the manifest
|
* Return an array containing information for the manifest
|
||||||
* @param $baseDir A
|
* @param $baseDir The root directory to analyse
|
||||||
|
* @param $excludedFolders An array folder names to exclude. These don't care about where the
|
||||||
|
* folder appears in the hierarchy, so be careful
|
||||||
*/
|
*/
|
||||||
static function get_manifest_info($baseDir, $tableList = null) {
|
static function get_manifest_info($baseDir, $excludedFolders = array()) {
|
||||||
// locate and include the exclude files
|
// locate and include the exclude files
|
||||||
$topLevel = scandir($baseDir);
|
$topLevel = scandir($baseDir);
|
||||||
foreach($topLevel as $file) {
|
foreach($topLevel as $file) {
|
||||||
@ -149,69 +155,45 @@ class ManifestBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Class manifest
|
// Project - used to give precedence to template files
|
||||||
|
$project = null;
|
||||||
|
|
||||||
|
// Class, CSS, template manifest
|
||||||
$classManifest = array();
|
$classManifest = array();
|
||||||
|
$templateManifest = array();
|
||||||
|
$cssManifest = array();
|
||||||
|
|
||||||
|
|
||||||
if(is_array(self::$restrict_to_modules) && count(self::$restrict_to_modules)) {
|
if(is_array(self::$restrict_to_modules) && count(self::$restrict_to_modules)) {
|
||||||
// $restrict_to_modules is set, so we include only those specified
|
// $restrict_to_modules is set, so we include only those specified
|
||||||
// modules
|
// modules
|
||||||
foreach(self::$restrict_to_modules as $module)
|
foreach(self::$restrict_to_modules as $module)
|
||||||
ManifestBuilder::getClassManifest($baseDir . '/' . $module,
|
ManifestBuilder::getClassManifest($baseDir . '/' . $module, $excludedFolders, $classManifest);
|
||||||
$classManifest);
|
|
||||||
} else {
|
} else {
|
||||||
// Include all directories which have an _config.php file but don't
|
// Include all directories which have an _config.php file but don't
|
||||||
// have an _manifest_exclude file
|
// have an _manifest_exclude file
|
||||||
$topLevel = scandir($baseDir);
|
$topLevel = scandir($baseDir);
|
||||||
foreach($topLevel as $filename) {
|
foreach($topLevel as $filename) {
|
||||||
if($filename[0] == '.') continue;
|
if($filename[0] == '.') continue;
|
||||||
|
if($filename == 'themes') continue;
|
||||||
|
if(in_array($filename, $excludedFolders)) continue;
|
||||||
|
|
||||||
if(@is_dir("$baseDir/$filename") &&
|
if(@is_dir("$baseDir/$filename") &&
|
||||||
file_exists("$baseDir/$filename/_config.php") &&
|
file_exists("$baseDir/$filename/_config.php") &&
|
||||||
!file_exists("$baseDir/$filename/_manifest_exclude")) {
|
!file_exists("$baseDir/$filename/_manifest_exclude")) {
|
||||||
ManifestBuilder::getClassManifest("$baseDir/$filename",
|
|
||||||
$classManifest);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$manifestInfo["globals"]["_CLASS_MANIFEST"] = $classManifest;
|
// Get classes, templates, and CSS files
|
||||||
|
ManifestBuilder::getClassManifest("$baseDir/$filename", $excludedFolders, $classManifest);
|
||||||
|
ManifestBuilder::getTemplateManifest($baseDir, $filename, $excludedFolders, $templateManifest, $cssManifest);
|
||||||
|
|
||||||
// Load the manifest in, so that the autoloader works
|
// List the _config.php files
|
||||||
global $_CLASS_MANIFEST;
|
|
||||||
$_CLASS_MANIFEST = $classManifest;
|
|
||||||
|
|
||||||
// Load in a temporary all-classes array for using while building the manifest
|
|
||||||
// @todo Manifestbuilder is tightly convoluted and gets really hard to debug. We have catch-22s betweeen
|
|
||||||
// db connection, value of project(), and ClassInfo responses... It needs to be untangled.
|
|
||||||
global $_ALL_CLASSES;
|
|
||||||
$allClasses = ManifestBuilder::allClasses($classManifest, array());
|
|
||||||
$_ALL_CLASSES = $allClasses;
|
|
||||||
|
|
||||||
// _config.php manifest
|
|
||||||
$topLevel = scandir($baseDir);
|
|
||||||
foreach($topLevel as $filename) {
|
|
||||||
if($filename[0] == '.') continue;
|
|
||||||
if(@is_dir("$baseDir/$filename/") &&
|
|
||||||
file_exists("$baseDir/$filename/_config.php") &&
|
|
||||||
!file_exists("$baseDir/$filename/_manifest_exclude")) {
|
|
||||||
$manifestInfo["require_once"][] = "$baseDir/$filename/_config.php";
|
$manifestInfo["require_once"][] = "$baseDir/$filename/_config.php";
|
||||||
// Include this so that we're set up for connecting to the database
|
// Find the $project variable in the relevant config file without having to execute the config file
|
||||||
// in the rest of the manifest builder
|
if(preg_match("/\\\$project\s*=\s*[^\n\r]+[\n\r]/", file_get_contents("$baseDir/$filename/_config.php"), $parts)) {
|
||||||
require_once("$baseDir/$filename/_config.php");
|
eval($parts[0]);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!project())
|
}
|
||||||
user_error("\$project isn't set", E_USER_WARNING);
|
|
||||||
|
|
||||||
// Template & CSS manifest
|
|
||||||
$templateManifest = array();
|
|
||||||
$cssManifest = array();
|
|
||||||
|
|
||||||
// Only include directories if they have an _config.php file
|
|
||||||
$topLevel = scandir($baseDir);
|
|
||||||
foreach($topLevel as $filename) {
|
|
||||||
if($filename[0] == '.') continue;
|
|
||||||
if($filename != 'themes' && @is_dir("$baseDir/$filename") && file_exists("$baseDir/$filename/_config.php")) {
|
|
||||||
ManifestBuilder::getTemplateManifest($baseDir, $filename, $templateManifest, $cssManifest);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,24 +204,22 @@ class ManifestBuilder {
|
|||||||
if(substr($themeDir,0,1) == '.') continue;
|
if(substr($themeDir,0,1) == '.') continue;
|
||||||
// The theme something_forum is understood as being a part of the theme something
|
// The theme something_forum is understood as being a part of the theme something
|
||||||
$themeName = strtok($themeDir, '_');
|
$themeName = strtok($themeDir, '_');
|
||||||
ManifestBuilder::getTemplateManifest($baseDir, "themes/$themeDir", $templateManifest, $cssManifest, $themeName);
|
ManifestBuilder::getTemplateManifest($baseDir, "themes/$themeDir", $excludedFolders, $templateManifest, $cssManifest, $themeName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Build class-info array from class manifest
|
||||||
|
$allClasses = ManifestBuilder::allClasses($classManifest);
|
||||||
|
|
||||||
// Ensure that any custom templates get favoured
|
// Ensure that any custom templates get favoured
|
||||||
ManifestBuilder::getTemplateManifest($baseDir, project(), $templateManifest, $cssManifest);
|
if(!$project) user_error("\$project isn't set", E_USER_WARNING);
|
||||||
|
ManifestBuilder::getTemplateManifest($baseDir, $project, $excludedFolders, $templateManifest, $cssManifest);
|
||||||
|
|
||||||
|
$manifestInfo["globals"]["_CLASS_MANIFEST"] = $classManifest;
|
||||||
|
$manifestInfo["globals"]["_ALL_CLASSES"] = $allClasses;
|
||||||
$manifestInfo["globals"]["_TEMPLATE_MANIFEST"] = $templateManifest;
|
$manifestInfo["globals"]["_TEMPLATE_MANIFEST"] = $templateManifest;
|
||||||
$manifestInfo["globals"]["_CSS_MANIFEST"] = $cssManifest;
|
$manifestInfo["globals"]["_CSS_MANIFEST"] = $cssManifest;
|
||||||
|
|
||||||
// Database manifest
|
|
||||||
$allClasses = ManifestBuilder::allClasses($classManifest, $tableList);
|
|
||||||
|
|
||||||
$manifestInfo["globals"]["_ALL_CLASSES"] = $allClasses;
|
|
||||||
|
|
||||||
global $_ALL_CLASSES;
|
|
||||||
$_ALL_CLASSES = $allClasses;
|
|
||||||
|
|
||||||
return $manifestInfo;
|
return $manifestInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,7 +231,7 @@ class ManifestBuilder {
|
|||||||
* @param string $folder The folder to traverse (recursively)
|
* @param string $folder The folder to traverse (recursively)
|
||||||
* @param array $classMap The already built class map
|
* @param array $classMap The already built class map
|
||||||
*/
|
*/
|
||||||
private static function getClassManifest($folder, &$classMap) {
|
private static function getClassManifest($folder, $excludedFolders, &$classMap) {
|
||||||
$items = scandir($folder);
|
$items = scandir($folder);
|
||||||
if($items) foreach($items as $item) {
|
if($items) foreach($items as $item) {
|
||||||
// Skip some specific PHP files
|
// Skip some specific PHP files
|
||||||
@ -276,8 +256,11 @@ class ManifestBuilder {
|
|||||||
if($item == 'lang' && @is_dir("$folder/$item") && ereg_replace("/[^/]+/\\.\\.","",$folder.'/..') == Director::baseFolder()) continue;
|
if($item == 'lang' && @is_dir("$folder/$item") && ereg_replace("/[^/]+/\\.\\.","",$folder.'/..') == Director::baseFolder()) continue;
|
||||||
|
|
||||||
if(@is_dir("$folder/$item")) {
|
if(@is_dir("$folder/$item")) {
|
||||||
|
// Folder exclusion - used to skip over tests/ folders
|
||||||
|
if(in_array($item, $excludedFolders)) continue;
|
||||||
|
|
||||||
// recurse into directories (if not in $ignore_folders)
|
// recurse into directories (if not in $ignore_folders)
|
||||||
ManifestBuilder::getClassManifest("$folder/$item", $classMap);
|
ManifestBuilder::getClassManifest("$folder/$item", $excludedFolders, $classMap);
|
||||||
} else {
|
} else {
|
||||||
// include item in the manifest
|
// include item in the manifest
|
||||||
$itemCode = substr($item,0,-4);
|
$itemCode = substr($item,0,-4);
|
||||||
@ -307,7 +290,7 @@ class ManifestBuilder {
|
|||||||
* Generates the template manifest - a list of all the .SS files in the
|
* Generates the template manifest - a list of all the .SS files in the
|
||||||
* application
|
* application
|
||||||
*/
|
*/
|
||||||
private static function getTemplateManifest($baseDir, $folder, &$templateManifest, &$cssManifest, $themeName = null) {
|
private static function getTemplateManifest($baseDir, $folder, $excludedFolders, &$templateManifest, &$cssManifest, $themeName = null) {
|
||||||
$items = scandir("$baseDir/$folder");
|
$items = scandir("$baseDir/$folder");
|
||||||
if($items) foreach($items as $item) {
|
if($items) foreach($items as $item) {
|
||||||
if(substr($item,0,1) == '.') continue;
|
if(substr($item,0,1) == '.') continue;
|
||||||
@ -334,7 +317,10 @@ class ManifestBuilder {
|
|||||||
|
|
||||||
|
|
||||||
} else if(@is_dir("$baseDir/$folder/$item")) {
|
} else if(@is_dir("$baseDir/$folder/$item")) {
|
||||||
ManifestBuilder::getTemplateManifest($baseDir, "$folder/$item", $templateManifest, $cssManifest, $themeName);
|
// Folder exclusion - used to skip over tests/ folders
|
||||||
|
if(in_array($item, $excludedFolders)) continue;
|
||||||
|
|
||||||
|
ManifestBuilder::getTemplateManifest($baseDir, "$folder/$item", $excludedFolders, $templateManifest, $cssManifest, $themeName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -342,16 +328,14 @@ class ManifestBuilder {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Include everything, so that actually *all* classes are available and
|
* Include everything, so that actually *all* classes are available and
|
||||||
* build a map of classes and their subclasses and the information if
|
* build a map of classes and their subclasses
|
||||||
* the class has a database table
|
|
||||||
*
|
*
|
||||||
* @param $classManifest An array of all Sapphire classes; keys are class names and values are filenames
|
* @param $classManifest An array of all Sapphire classes; keys are class names and values are filenames
|
||||||
* @param $tables An array of the tables that exist in the database
|
|
||||||
*
|
*
|
||||||
* @return array Returns an array that holds all class relevant
|
* @return array Returns an array that holds all class relevant
|
||||||
* information.
|
* information.
|
||||||
*/
|
*/
|
||||||
private static function allClasses($classManifest, $tables = null) {
|
private static function allClasses($classManifest) {
|
||||||
self::$classArray = array();
|
self::$classArray = array();
|
||||||
self::$extendsArray = array();
|
self::$extendsArray = array();
|
||||||
self::$implementsArray = array();
|
self::$implementsArray = array();
|
||||||
@ -369,7 +353,6 @@ class ManifestBuilder {
|
|||||||
|
|
||||||
foreach(self::$classArray as $class => $info) {
|
foreach(self::$classArray as $class => $info) {
|
||||||
$allClasses['exists'][$class] = $class;
|
$allClasses['exists'][$class] = $class;
|
||||||
if(isset($tables[strtolower($class)])) $allClasses['hastable'][$class] = $class;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build a map of classes and their subclasses
|
// Build a map of classes and their subclasses
|
||||||
@ -377,7 +360,6 @@ class ManifestBuilder {
|
|||||||
|
|
||||||
foreach($_classes as $class) {
|
foreach($_classes as $class) {
|
||||||
$allClasses['exists'][$class] = $class;
|
$allClasses['exists'][$class] = $class;
|
||||||
if(isset($tables[strtolower($class)])) $allClasses['hastable'][$class] = $class;
|
|
||||||
foreach($_classes as $subclass) {
|
foreach($_classes as $subclass) {
|
||||||
if(is_subclass_of($class, $subclass)) $allClasses['parents'][$class][$subclass] = $subclass;
|
if(is_subclass_of($class, $subclass)) $allClasses['parents'][$class][$subclass] = $subclass;
|
||||||
if(is_subclass_of($subclass, $class)) $allClasses['children'][$class][$subclass] = $subclass;
|
if(is_subclass_of($subclass, $class)) $allClasses['children'][$class][$subclass] = $subclass;
|
||||||
@ -449,6 +431,8 @@ class ManifestBuilder {
|
|||||||
* @return TokenisedRegularExpression
|
* @return TokenisedRegularExpression
|
||||||
*/
|
*/
|
||||||
public static function getClassDefParser() {
|
public static function getClassDefParser() {
|
||||||
|
require_once('core/TokenisedRegularExpression.php');
|
||||||
|
|
||||||
return new TokenisedRegularExpression(array(
|
return new TokenisedRegularExpression(array(
|
||||||
0 => T_CLASS,
|
0 => T_CLASS,
|
||||||
1 => T_WHITESPACE,
|
1 => T_WHITESPACE,
|
||||||
@ -474,6 +458,8 @@ class ManifestBuilder {
|
|||||||
* @return TokenisedRegularExpression
|
* @return TokenisedRegularExpression
|
||||||
*/
|
*/
|
||||||
public static function getInterfaceDefParser() {
|
public static function getInterfaceDefParser() {
|
||||||
|
require_once('core/TokenisedRegularExpression.php');
|
||||||
|
|
||||||
return new TokenisedRegularExpression(array(
|
return new TokenisedRegularExpression(array(
|
||||||
0 => T_INTERFACE,
|
0 => T_INTERFACE,
|
||||||
1 => T_WHITESPACE,
|
1 => T_WHITESPACE,
|
||||||
@ -550,68 +536,6 @@ class ManifestBuilder {
|
|||||||
}
|
}
|
||||||
return $results;;
|
return $results;;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the active table list in the class info in the manifest, but leaves everything else as-is.
|
|
||||||
* Much quicker to run than compileManifest :-)
|
|
||||||
*
|
|
||||||
* @param $tableList The list of tables to load into the manifest
|
|
||||||
* @param $allClassesArray The $_ALL_CLASSES array that should be updated
|
|
||||||
*/
|
|
||||||
static function update_db_tables($tableList, &$allClassesArray) {
|
|
||||||
if(!isset($allClassesArray['exists'])) return;
|
|
||||||
|
|
||||||
$allClassesArray['hastable'] = array();
|
|
||||||
|
|
||||||
$tables = array();
|
|
||||||
foreach($tableList as $table) $tables[$table] = true;
|
|
||||||
|
|
||||||
// We need to iterate through the full class lists, because the table names come out in lowercase
|
|
||||||
foreach($allClassesArray['exists'] as $class) {
|
|
||||||
if(isset($tables[strtolower($class)])) $allClassesArray['hastable'][$class] = $class;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write the manifest file, containing the updated values in the applicable globals
|
|
||||||
*/
|
|
||||||
static function write_manifest() {
|
|
||||||
global $_CLASS_MANIFEST, $_TEMPLATE_MANIFEST, $_CSS_MANIFEST, $_ALL_CLASSES;
|
|
||||||
|
|
||||||
$manifest = "\$_CLASS_MANIFEST = " . var_export($_CLASS_MANIFEST, true) . ";\n";
|
|
||||||
|
|
||||||
// Config manifest
|
|
||||||
$baseDir = dirname($_SERVER['SCRIPT_FILENAME']) . "/..";
|
|
||||||
$baseDir = ereg_replace("/[^/]+/\\.\\.","",$baseDir);
|
|
||||||
$baseDir = preg_replace("/\\\\/", "/", $baseDir);
|
|
||||||
$topLevel = scandir($baseDir);
|
|
||||||
|
|
||||||
foreach($topLevel as $filename) {
|
|
||||||
if($filename[0] == '.') continue;
|
|
||||||
if(@is_dir("$baseDir/$filename/") && file_exists("$baseDir/$filename/_config.php")) {
|
|
||||||
$manifest .= "require_once(\"$baseDir/$filename/_config.php\");\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$manifest .= "\$_TEMPLATE_MANIFEST = " . var_export($_TEMPLATE_MANIFEST, true) . ";\n";
|
|
||||||
$manifest .= "\$_CSS_MANIFEST = " . var_export($_CSS_MANIFEST, true) . ";\n";
|
|
||||||
$manifest .= "\$_ALL_CLASSES = " . var_export($_ALL_CLASSES, true) . ";\n";
|
|
||||||
$manifest = "<?php\n$manifest\n?>";
|
|
||||||
|
|
||||||
if($fh = fopen(MANIFEST_FILE,"w")) {
|
|
||||||
fwrite($fh, $manifest);
|
|
||||||
fclose($fh);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
die("Cannot write manifest file! Check permissions of " . MANIFEST_FILE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static function includeEverything() {
|
|
||||||
global $_CLASS_MANIFEST;
|
|
||||||
foreach($_CLASS_MANIFEST as $classFile) require_once($classFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -76,15 +76,16 @@ class Controller extends RequestHandler {
|
|||||||
*/
|
*/
|
||||||
function init() {
|
function init() {
|
||||||
// Test and development sites should be secured, via basic-auth
|
// Test and development sites should be secured, via basic-auth
|
||||||
if(ClassInfo::hasTable("Group") && ClassInfo::hasTable("Member") && Director::isTest() && $this->basicAuthEnabled) {
|
if(Director::isTest() && $this->basicAuthEnabled && Security::database_is_ready()) {
|
||||||
BasicAuth::requireLogin("SilverStripe test website. Use your CMS login", "ADMIN");
|
BasicAuth::requireLogin("SilverStripe test website. Use your CMS login", "ADMIN");
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
Cookie::set("PastVisitor", true);
|
Cookie::set("PastVisitor", true);
|
||||||
|
|
||||||
// ClassInfo::hasTable() called to ensure that we're not in a very-first-setup stage
|
// Directly access the session variable just in case the Group or Member tables don't yet exist
|
||||||
if(ClassInfo::hasTable("Group") && ClassInfo::hasTable("Member") && ($member = Member::currentUser())) {
|
if(Session::get('loggedInAs')) {
|
||||||
|
$member = Member::currentUser();
|
||||||
Cookie::set("PastMember", true);
|
Cookie::set("PastMember", true);
|
||||||
DB::query("UPDATE Member SET LastVisited = NOW() WHERE ID = $member->ID", null);
|
DB::query("UPDATE Member SET LastVisited = NOW() WHERE ID = $member->ID", null);
|
||||||
}
|
}
|
||||||
|
@ -546,7 +546,8 @@ class Director {
|
|||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public static function is_cli() {
|
public static function is_cli() {
|
||||||
return preg_match('/cli-script\.php/', $_SERVER['SCRIPT_NAME']);
|
return (!isset($_SERVER['HTTP_HOST']) && preg_match('/install\.php/', $_SERVER['SCRIPT_NAME']))
|
||||||
|
|| preg_match('/cli-script\.php/', $_SERVER['SCRIPT_NAME']);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -680,7 +681,7 @@ class Director {
|
|||||||
|
|
||||||
// Use ?isDev=1 to get development access on the live server
|
// Use ?isDev=1 to get development access on the live server
|
||||||
if(isset($_GET['isDev'])) {
|
if(isset($_GET['isDev'])) {
|
||||||
if(ClassInfo::ready()) {
|
if(Security::database_is_ready()) {
|
||||||
BasicAuth::requireLogin("SilverStripe developer access. Use your CMS login", "ADMIN");
|
BasicAuth::requireLogin("SilverStripe developer access. Use your CMS login", "ADMIN");
|
||||||
$_SESSION['isDev'] = $_GET['isDev'];
|
$_SESSION['isDev'] = $_GET['isDev'];
|
||||||
} else {
|
} else {
|
||||||
|
@ -693,7 +693,7 @@ class DataObject extends ViewableData implements DataObjectInterface,i18nEntityP
|
|||||||
// No changes made
|
// No changes made
|
||||||
if($this->changed) {
|
if($this->changed) {
|
||||||
foreach($this->getClassAncestry() as $ancestor) {
|
foreach($this->getClassAncestry() as $ancestor) {
|
||||||
if(ClassInfo::hasTable($ancestor))
|
if(self::has_own_table($ancestor))
|
||||||
$ancestry[] = $ancestor;
|
$ancestry[] = $ancestor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -758,7 +758,7 @@ class DataObject extends ViewableData implements DataObjectInterface,i18nEntityP
|
|||||||
}
|
}
|
||||||
|
|
||||||
// In cases where there are no fields, this 'stub' will get picked up on
|
// In cases where there are no fields, this 'stub' will get picked up on
|
||||||
if(ClassInfo::hasTable($class)) {
|
if(self::has_own_table($class)) {
|
||||||
$manipulation[$class]['command'] = $dbCommand;
|
$manipulation[$class]['command'] = $dbCommand;
|
||||||
$manipulation[$class]['id'] = $this->record['ID'];
|
$manipulation[$class]['id'] = $this->record['ID'];
|
||||||
} else {
|
} else {
|
||||||
@ -846,7 +846,7 @@ class DataObject extends ViewableData implements DataObjectInterface,i18nEntityP
|
|||||||
user_error("$this->class has a broken onBeforeDelete() function. Make sure that you call parent::onBeforeDelete().", E_USER_ERROR);
|
user_error("$this->class has a broken onBeforeDelete() function. Make sure that you call parent::onBeforeDelete().", E_USER_ERROR);
|
||||||
}
|
}
|
||||||
foreach($this->getClassAncestry() as $ancestor) {
|
foreach($this->getClassAncestry() as $ancestor) {
|
||||||
if(ClassInfo::hastable($ancestor)) {
|
if(self::has_own_table($ancestor)) {
|
||||||
$sql = new SQLQuery();
|
$sql = new SQLQuery();
|
||||||
$sql->delete = true;
|
$sql->delete = true;
|
||||||
$sql->from[$ancestor] = "`$ancestor`";
|
$sql->from[$ancestor] = "`$ancestor`";
|
||||||
@ -1748,6 +1748,26 @@ class DataObject extends ViewableData implements DataObjectInterface,i18nEntityP
|
|||||||
return isset($fieldMap[$field]) ? strtok($fieldMap[$field],'(') : null;
|
return isset($fieldMap[$field]) ? strtok($fieldMap[$field],'(') : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if given class has its own table.
|
||||||
|
* Uses the rules for whether the table should exist rather than actually looking in the database.
|
||||||
|
*/
|
||||||
|
public function has_own_table($dataClass) {
|
||||||
|
if(!is_subclass_of($dataClass,'DataObject')) return false;
|
||||||
|
if(!isset(self::$cache_has_own_table[$dataClass])) {
|
||||||
|
if(get_parent_class($dataClass) == 'DataObject') {
|
||||||
|
self::$cache_has_own_table[$dataClass] = true;
|
||||||
|
} else {
|
||||||
|
$sng = singleton($dataClass);
|
||||||
|
self::$cache_has_own_table[$dataClass] = $sng->uninherited('db',true) || $sng->uninherited('has_one',true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return self::$cache_has_own_table[$dataClass];
|
||||||
|
}
|
||||||
|
|
||||||
|
private static $cache_has_own_table = array();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the member is allowed to do the given action.
|
* Returns true if the member is allowed to do the given action.
|
||||||
*
|
*
|
||||||
|
@ -163,10 +163,6 @@ class DatabaseAdmin extends Controller {
|
|||||||
}
|
}
|
||||||
$conn->endSchemaUpdate();
|
$conn->endSchemaUpdate();
|
||||||
|
|
||||||
global $_ALL_CLASSES;
|
|
||||||
ManifestBuilder::update_db_tables(DB::getConn()->tableList(), $_ALL_CLASSES);
|
|
||||||
if(!$testMode) ManifestBuilder::write_manifest();
|
|
||||||
|
|
||||||
if($populate) {
|
if($populate) {
|
||||||
if(!$quiet) {
|
if(!$quiet) {
|
||||||
if(Director::is_cli()) echo "\nCREATING DATABASE RECORDS\n\n";
|
if(Director::is_cli()) echo "\nCREATING DATABASE RECORDS\n\n";
|
||||||
|
@ -51,6 +51,7 @@ class TestRunner extends Controller {
|
|||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
parent::init();
|
parent::init();
|
||||||
|
ManifestBuilder::load_test_manifest();
|
||||||
if (!self::$default_reporter) self::set_reporter(Director::is_cli() ? 'CliDebugView' : 'DebugView');
|
if (!self::$default_reporter) self::set_reporter(Director::is_cli() ? 'CliDebugView' : 'DebugView');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,7 +96,7 @@ class TestRunner extends Controller {
|
|||||||
|
|
||||||
function coverage() {
|
function coverage() {
|
||||||
if(hasPhpUnit()) {
|
if(hasPhpUnit()) {
|
||||||
ManifestBuilder::includeEverything();
|
ManifestBuilder::load_all_classes();
|
||||||
$tests = ClassInfo::subclassesFor('SapphireTest');
|
$tests = ClassInfo::subclassesFor('SapphireTest');
|
||||||
array_shift($tests);
|
array_shift($tests);
|
||||||
unset($tests['FunctionalTest']);
|
unset($tests['FunctionalTest']);
|
||||||
|
@ -525,6 +525,24 @@ class DataObjectTest extends SapphireTest {
|
|||||||
$this->assertEquals("1001", DB::query("SELECT ID FROM DataObjectTest_SubTeam WHERE SubclassDatabaseField = 'asdfasdf'")->value());
|
$this->assertEquals("1001", DB::query("SELECT ID FROM DataObjectTest_SubTeam WHERE SubclassDatabaseField = 'asdfasdf'")->value());
|
||||||
$this->assertEquals("1001", DB::query("SELECT ID FROM DataObjectTest_Team WHERE Title = 'asdfasdf'")->value());
|
$this->assertEquals("1001", DB::query("SELECT ID FROM DataObjectTest_Team WHERE Title = 'asdfasdf'")->value());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function TestHasOwnTable() {
|
||||||
|
/* Test DataObject::has_own_table() returns true if the object has $has_one or $db values */
|
||||||
|
$this->assertTrue(DataObject::has_own_table("DataObjectTest_Player"));
|
||||||
|
$this->assertTrue(DataObject::has_own_table("DataObjectTest_Team"));
|
||||||
|
$this->assertTrue(DataObject::has_own_table("DataObjectTest_FunnyFieldNames"));
|
||||||
|
|
||||||
|
/* Root DataObject that always have a table, even if they lack both $db and $has_one */
|
||||||
|
$this->assertTrue(DataObject::has_own_table("DataObjectTest_FieldlessTable"));
|
||||||
|
|
||||||
|
/* Subclasses without $db or $has_one don't have a table */
|
||||||
|
$this->assertFalse(DataObject::has_own_table("DataObjectTest_FieldlessSubTable"));
|
||||||
|
|
||||||
|
/* Return false if you don't pass it a subclass of DataObject */
|
||||||
|
$this->assertFalse(DataObject::has_own_table("DataObject"));
|
||||||
|
$this->assertFalse(DataObject::has_own_table("ViewableData"));
|
||||||
|
$this->assertFalse(DataObject::has_own_table("ThisIsntADataObject"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DataObjectTest_Player extends Member implements TestOnly {
|
class DataObjectTest_Player extends Member implements TestOnly {
|
||||||
@ -574,6 +592,13 @@ class DataObjectTest_SubTeam extends DataObjectTest_Team implements TestOnly {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class DataObjectTest_FieldlessTable extends DataObject implements TestOnly {
|
||||||
|
}
|
||||||
|
|
||||||
|
class DataObjectTest_FieldlessSubTable extends DataObjectTest_Team implements TestOnly {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class DataObjectTest_Team_Decorator extends DataObjectDecorator implements TestOnly {
|
class DataObjectTest_Team_Decorator extends DataObjectDecorator implements TestOnly {
|
||||||
|
|
||||||
function extraStatics() {
|
function extraStatics() {
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
class ManifestBuilderTest extends SapphireTest {
|
class ManifestBuilderTest extends SapphireTest {
|
||||||
function testManifest() {
|
function testManifest() {
|
||||||
$baseFolder = TEMP_FOLDER . '/manifest-test';
|
$baseFolder = TEMP_FOLDER . '/manifest-test';
|
||||||
$manifestInfo = ManifestBuilder::get_manifest_info($baseFolder, DB::getConn()->tableList());
|
$manifestInfo = ManifestBuilder::get_manifest_info($baseFolder);
|
||||||
global $project;
|
global $project;
|
||||||
|
|
||||||
$this->assertEquals("$baseFolder/sapphire/MyClass.php", $manifestInfo['globals']['_CLASS_MANIFEST']['MyClass']);
|
$this->assertEquals("$baseFolder/sapphire/MyClass.php", $manifestInfo['globals']['_CLASS_MANIFEST']['MyClass']);
|
||||||
@ -36,42 +36,37 @@ class ManifestBuilderTest extends SapphireTest {
|
|||||||
$baseFolder = TEMP_FOLDER . '/manifest-test';
|
$baseFolder = TEMP_FOLDER . '/manifest-test';
|
||||||
global $project;
|
global $project;
|
||||||
|
|
||||||
$manifestInfo = ManifestBuilder::get_manifest_info($baseFolder, DB::getConn()->tableList());
|
$manifestInfo = ManifestBuilder::get_manifest_info($baseFolder);
|
||||||
|
|
||||||
/* Our fixture defines the class MyClass_InComment inside a comment, so it shouldn't be included in the class manifest. */
|
/* Our fixture defines the class MyClass_InComment inside a comment, so it shouldn't be included in the class manifest. */
|
||||||
$this->assertNotContains('MyClass_InComment', array_keys($manifestInfo['globals']['_CLASS_MANIFEST']));
|
$this->assertNotContains('MyClass_InComment', array_keys($manifestInfo['globals']['_CLASS_MANIFEST']));
|
||||||
$this->assertNotContains('MyClass_InComment', array_keys($manifestInfo['globals']['_ALL_CLASSES']['exists']));
|
$this->assertNotContains('MyClass_InComment', array_keys($manifestInfo['globals']['_ALL_CLASSES']['exists']));
|
||||||
$this->assertNotContains('MyClass_InComment', array_keys($manifestInfo['globals']['_ALL_CLASSES']['parents']));
|
$this->assertNotContains('MyClass_InComment', array_keys($manifestInfo['globals']['_ALL_CLASSES']['parents']));
|
||||||
$this->assertNotContains('MyClass_InComment', array_keys($manifestInfo['globals']['_ALL_CLASSES']['hastable']));
|
|
||||||
|
|
||||||
/* Our fixture defines the class MyClass_InSlashSlashComment inside a //-style comment, so it shouldn't be included in the class manifest. */
|
/* Our fixture defines the class MyClass_InSlashSlashComment inside a //-style comment, so it shouldn't be included in the class manifest. */
|
||||||
$this->assertNotContains('MyClass_InSlashSlashComment', array_keys($manifestInfo['globals']['_CLASS_MANIFEST']));
|
$this->assertNotContains('MyClass_InSlashSlashComment', array_keys($manifestInfo['globals']['_CLASS_MANIFEST']));
|
||||||
$this->assertNotContains('MyClass_InSlashSlashComment', array_keys($manifestInfo['globals']['_ALL_CLASSES']['exists']));
|
$this->assertNotContains('MyClass_InSlashSlashComment', array_keys($manifestInfo['globals']['_ALL_CLASSES']['exists']));
|
||||||
$this->assertNotContains('MyClass_InSlashSlashComment', array_keys($manifestInfo['globals']['_ALL_CLASSES']['parents']));
|
$this->assertNotContains('MyClass_InSlashSlashComment', array_keys($manifestInfo['globals']['_ALL_CLASSES']['parents']));
|
||||||
$this->assertNotContains('MyClass_InSlashSlashComment', array_keys($manifestInfo['globals']['_ALL_CLASSES']['hastable']));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function testManifestIgnoresClassesInStrings() {
|
function testManifestIgnoresClassesInStrings() {
|
||||||
$baseFolder = TEMP_FOLDER . '/manifest-test';
|
$baseFolder = TEMP_FOLDER . '/manifest-test';
|
||||||
$manifestInfo = ManifestBuilder::get_manifest_info($baseFolder, DB::getConn()->tableList());
|
$manifestInfo = ManifestBuilder::get_manifest_info($baseFolder);
|
||||||
|
|
||||||
/* If a class defintion is listed in a single quote string, then it shouldn't be inlcuded. Here we have put a class definition for MyClass_InSingleQuoteString inside a single-quoted string */
|
/* If a class defintion is listed in a single quote string, then it shouldn't be inlcuded. Here we have put a class definition for MyClass_InSingleQuoteString inside a single-quoted string */
|
||||||
$this->assertNotContains('MyClass_InSingleQuoteString', array_keys($manifestInfo['globals']['_CLASS_MANIFEST']));
|
$this->assertNotContains('MyClass_InSingleQuoteString', array_keys($manifestInfo['globals']['_CLASS_MANIFEST']));
|
||||||
$this->assertNotContains('MyClass_InSingleQuoteString', array_keys($manifestInfo['globals']['_ALL_CLASSES']['exists']));
|
$this->assertNotContains('MyClass_InSingleQuoteString', array_keys($manifestInfo['globals']['_ALL_CLASSES']['exists']));
|
||||||
$this->assertNotContains('MyClass_InSingleQuoteString', array_keys($manifestInfo['globals']['_ALL_CLASSES']['parents']));
|
$this->assertNotContains('MyClass_InSingleQuoteString', array_keys($manifestInfo['globals']['_ALL_CLASSES']['parents']));
|
||||||
$this->assertNotContains('MyClass_InSingleQuoteString', array_keys($manifestInfo['globals']['_ALL_CLASSES']['hastable']));
|
|
||||||
|
|
||||||
/* Ditto for double quotes. Here we have put a class definition for MyClass_InDoubleQuoteString inside a double-quoted string. */
|
/* Ditto for double quotes. Here we have put a class definition for MyClass_InDoubleQuoteString inside a double-quoted string. */
|
||||||
$this->assertNotContains('MyClass_InDoubleQuoteString', array_keys($manifestInfo['globals']['_CLASS_MANIFEST']));
|
$this->assertNotContains('MyClass_InDoubleQuoteString', array_keys($manifestInfo['globals']['_CLASS_MANIFEST']));
|
||||||
$this->assertNotContains('MyClass_InDoubleQuoteString', array_keys($manifestInfo['globals']['_ALL_CLASSES']['exists']));
|
$this->assertNotContains('MyClass_InDoubleQuoteString', array_keys($manifestInfo['globals']['_ALL_CLASSES']['exists']));
|
||||||
$this->assertNotContains('MyClass_InDoubleQuoteString', array_keys($manifestInfo['globals']['_ALL_CLASSES']['parents']));
|
$this->assertNotContains('MyClass_InDoubleQuoteString', array_keys($manifestInfo['globals']['_ALL_CLASSES']['parents']));
|
||||||
$this->assertNotContains('MyClass_InDoubleQuoteString', array_keys($manifestInfo['globals']['_ALL_CLASSES']['hastable']));
|
|
||||||
|
|
||||||
/* Finally, we need to ensure that class definitions inside heredoc strings aren't included. Here, we have defined the class MyClass_InHeredocString inside a heredoc string. */
|
/* Finally, we need to ensure that class definitions inside heredoc strings aren't included. Here, we have defined the class MyClass_InHeredocString inside a heredoc string. */
|
||||||
$this->assertNotContains('MyClass_InHeredocString', array_keys($manifestInfo['globals']['_CLASS_MANIFEST']));
|
$this->assertNotContains('MyClass_InHeredocString', array_keys($manifestInfo['globals']['_CLASS_MANIFEST']));
|
||||||
$this->assertNotContains('MyClass_InHeredocString', array_keys($manifestInfo['globals']['_ALL_CLASSES']['exists']));
|
$this->assertNotContains('MyClass_InHeredocString', array_keys($manifestInfo['globals']['_ALL_CLASSES']['exists']));
|
||||||
$this->assertNotContains('MyClass_InHeredocString', array_keys($manifestInfo['globals']['_ALL_CLASSES']['parents']));
|
$this->assertNotContains('MyClass_InHeredocString', array_keys($manifestInfo['globals']['_ALL_CLASSES']['parents']));
|
||||||
$this->assertNotContains('MyClass_InHeredocString', array_keys($manifestInfo['globals']['_ALL_CLASSES']['hastable']));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ class RestfulServiceTest extends SapphireTest {
|
|||||||
'test1c' => 'And now for a string test' // string test
|
'test1c' => 'And now for a string test' // string test
|
||||||
);
|
);
|
||||||
$connection->setQueryString($test1params);
|
$connection->setQueryString($test1params);
|
||||||
$test1 = $connection->request('RestfulServiceTest_Controller')->getBody();
|
$test1 = $connection->request('RestfulServiceTest_Controller?usetestmanifest=1')->getBody();
|
||||||
foreach ($test1params as $key => $value) {
|
foreach ($test1params as $key => $value) {
|
||||||
$this->assertContains("<request_item name=\"$key\">$value</request_item>", $test1);
|
$this->assertContains("<request_item name=\"$key\">$value</request_item>", $test1);
|
||||||
$this->assertContains("<get_item name=\"$key\">$value</get_item>", $test1);
|
$this->assertContains("<get_item name=\"$key\">$value</get_item>", $test1);
|
||||||
@ -20,7 +20,7 @@ class RestfulServiceTest extends SapphireTest {
|
|||||||
'test2b' => '%\'"@?=;:/,$', // special character checks
|
'test2b' => '%\'"@?=;:/,$', // special character checks
|
||||||
'test2c' => 'And now for a string test', // string test
|
'test2c' => 'And now for a string test', // string test
|
||||||
);
|
);
|
||||||
$test2suburl = 'RestfulServiceTest_Controller/?';
|
$test2suburl = 'RestfulServiceTest_Controller/?usetestmanifest=1&';
|
||||||
foreach ($test2params as $key=>$value) {
|
foreach ($test2params as $key=>$value) {
|
||||||
$test2suburl .= "$key=$value&";
|
$test2suburl .= "$key=$value&";
|
||||||
}
|
}
|
||||||
@ -46,7 +46,7 @@ class RestfulServiceTest extends SapphireTest {
|
|||||||
'test1b' => mt_rand(),
|
'test1b' => mt_rand(),
|
||||||
'test1c' => 'And now for a string test'
|
'test1c' => 'And now for a string test'
|
||||||
);
|
);
|
||||||
$test1 = $connection->request('RestfulServiceTest_Controller', 'POST', $test1params)->getBody();
|
$test1 = $connection->request('RestfulServiceTest_Controller/?usetestmanifest=1', 'POST', $test1params)->getBody();
|
||||||
foreach ($test1params as $key => $value) {
|
foreach ($test1params as $key => $value) {
|
||||||
$this->assertContains("<request_item name=\"$key\">$value</request_item>", $test1);
|
$this->assertContains("<request_item name=\"$key\">$value</request_item>", $test1);
|
||||||
$this->assertContains("<post_item name=\"$key\">$value</post_item>", $test1);
|
$this->assertContains("<post_item name=\"$key\">$value</post_item>", $test1);
|
||||||
|
Loading…
Reference in New Issue
Block a user