Merge branch '5' into 6

This commit is contained in:
github-actions 2024-03-19 23:26:27 +00:00
commit 2b296b6481
7 changed files with 90 additions and 60 deletions

View File

@ -35,6 +35,13 @@ class Environment
*/ */
protected static $env = []; protected static $env = [];
/**
* Used by unit tests to override `isCli()`
* This is not config. Use reflection to change the value
* @internal
*/
private static ?bool $isCliOverride = null;
/** /**
* Extract env vars prior to modification * Extract env vars prior to modification
* *
@ -251,6 +258,9 @@ class Environment
*/ */
public static function isCli() public static function isCli()
{ {
if (self::$isCliOverride !== null) {
return self::$isCliOverride;
}
return in_array(strtolower(php_sapi_name() ?? ''), ['cli', 'phpdbg']); return in_array(strtolower(php_sapi_name() ?? ''), ['cli', 'phpdbg']);
} }
} }

View File

@ -138,8 +138,7 @@ class HTMLEditorField extends TextareaField
// Sanitise if requested // Sanitise if requested
$htmlValue = HTMLValue::create($this->Value()); $htmlValue = HTMLValue::create($this->Value());
if (HTMLEditorField::config()->sanitise_server_side) { if (HTMLEditorField::config()->sanitise_server_side) {
$config = $this->getEditorConfig(); $santiser = HTMLEditorSanitiser::create(HTMLEditorConfig::get_active());
$santiser = HTMLEditorSanitiser::create($config);
$santiser->sanitise($htmlValue); $santiser->sanitise($htmlValue);
} }

View File

@ -3,6 +3,7 @@
namespace SilverStripe\ORM\Connect; namespace SilverStripe\ORM\Connect;
use InvalidArgumentException; use InvalidArgumentException;
use LogicException;
use SilverStripe\Control\Director; use SilverStripe\Control\Director;
use SilverStripe\Core\Config\Configurable; use SilverStripe\Core\Config\Configurable;
use SilverStripe\Core\Convert; use SilverStripe\Core\Convert;
@ -400,8 +401,8 @@ class DBQueryBuilder
*/ */
public function buildUpdateFragment(SQLUpdate $query, array &$parameters) public function buildUpdateFragment(SQLUpdate $query, array &$parameters)
{ {
$table = $query->getTable(); $nl = $this->getSeparator();
$text = "UPDATE $table"; $text = "{$nl}UPDATE " . $this->getTableWithJoins($query, $parameters);
// Join SET components together, considering parameters // Join SET components together, considering parameters
$parts = []; $parts = [];
@ -427,26 +428,13 @@ class DBQueryBuilder
*/ */
public function buildFromFragment(SQLConditionalExpression $query, array &$parameters) public function buildFromFragment(SQLConditionalExpression $query, array &$parameters)
{ {
$from = $query->getJoins($joinParameters); $from = $this->getTableWithJoins($query, $parameters, true);
$tables = []; if ($from === '') {
$joins = [];
// E.g. a naive "Select 1" statement is valid SQL
if (empty($from)) {
return ''; return '';
} }
foreach ($from as $joinOrTable) {
if (preg_match(SQLConditionalExpression::getJoinRegex(), $joinOrTable)) {
$joins[] = $joinOrTable;
} else {
$tables[] = $joinOrTable;
}
}
$parameters = array_merge($parameters, $joinParameters);
$nl = $this->getSeparator(); $nl = $this->getSeparator();
return "{$nl}FROM " . implode(', ', $tables) . ' ' . implode(' ', $joins); return "{$nl}FROM " . $from;
} }
/** /**
@ -601,4 +589,34 @@ class DBQueryBuilder
} }
return $clause; return $clause;
} }
/**
* Get the name of the table (along with any join clauses) the query will operate on.
*/
private function getTableWithJoins(SQLConditionalExpression $query, array &$parameters, bool $allowEmpty = false): string
{
$from = $query->getJoins($joinParameters);
$tables = [];
$joins = [];
// E.g. a naive "Select 1" statement is valid SQL
if (empty($from)) {
if ($allowEmpty) {
return '';
} else {
throw new LogicException('Query have at least one table to operate on.');
}
}
foreach ($from as $joinOrTable) {
if (preg_match(SQLConditionalExpression::getJoinRegex(), $joinOrTable)) {
$joins[] = $joinOrTable;
} else {
$tables[] = $joinOrTable;
}
}
$parameters = array_merge($parameters, $joinParameters);
return implode(', ', $tables) . ' ' . implode(' ', $joins);
}
} }

View File

@ -12,7 +12,6 @@ use SilverStripe\Control\Director;
use SilverStripe\Core\Config\Config; use SilverStripe\Core\Config\Config;
use SilverStripe\Dev\CSSContentParser; use SilverStripe\Dev\CSSContentParser;
use SilverStripe\Dev\FunctionalTest; use SilverStripe\Dev\FunctionalTest;
use SilverStripe\Forms\HTMLEditor\HTMLEditorConfig;
use SilverStripe\Forms\HTMLEditor\HTMLEditorField; use SilverStripe\Forms\HTMLEditor\HTMLEditorField;
use SilverStripe\Forms\HTMLEditor\TinyMCEConfig; use SilverStripe\Forms\HTMLEditor\TinyMCEConfig;
use SilverStripe\Forms\HTMLReadonlyField; use SilverStripe\Forms\HTMLReadonlyField;
@ -232,43 +231,6 @@ EOS
); );
} }
public function testFieldConfigSanitization()
{
$obj = TestObject::create();
$editor = HTMLEditorField::create('Content');
$defaultValidElements = [
'@[id|class|style|title|data*]',
'a[id|rel|dir|tabindex|accesskey|type|name|href|target|title|class]',
'-strong/-b[class]',
'-em/-i[class]',
'-ol[class]',
'#p[id|dir|class|align|style]',
'-li[class]',
'br',
'-span[class|align|style]',
'-ul[class]',
'-h3[id|dir|class|align|style]',
'-h2[id|dir|class|align|style]',
'hr[class]',
];
$restrictedConfig = HTMLEditorConfig::get('restricted');
$restrictedConfig->setOption('valid_elements', implode(',', $defaultValidElements));
$editor->setEditorConfig($restrictedConfig);
$expectedHtmlString = '<p>standard text</p>Header';
$htmlValue = '<p>standard text</p><table><tbody><tr><th></th></tr><tr><td>Header</td></tr></tbody><tbody></tbody></table>';
$editor->setValue($htmlValue);
$editor->saveInto($obj);
$this->assertEquals($expectedHtmlString, $obj->Content, 'Table is not removed');
$defaultConfig = HTMLEditorConfig::get('default');
$editor->setEditorConfig($defaultConfig);
$editor->setValue($htmlValue);
$editor->saveInto($obj);
$this->assertEquals($htmlValue, $obj->Content, 'Table is removed');
}
public function testGetAttributes() public function testGetAttributes()
{ {
// If silverstripe/admin isn't installed, we can't get TinyMCEConfig attributes // If silverstripe/admin isn't installed, we can't get TinyMCEConfig attributes

View File

@ -12,12 +12,12 @@ use SilverStripe\Dev\SapphireTest;
*/ */
class SQLUpdateTest extends SapphireTest class SQLUpdateTest extends SapphireTest
{ {
public static $fixture_file = 'SQLUpdateTest.yml'; public static $fixture_file = 'SQLUpdateTest.yml';
protected static $extra_dataobjects = [ protected static $extra_dataobjects = [
SQLUpdateTest\TestBase::class, SQLUpdateTest\TestBase::class,
SQLUpdateTest\TestChild::class SQLUpdateTest\TestChild::class,
SQLUpdateTest\TestOther::class,
]; ];
public function testEmptyQueryReturnsNothing() public function testEmptyQueryReturnsNothing()
@ -46,4 +46,25 @@ class SQLUpdateTest extends SapphireTest
$item = DataObject::get_one(SQLUpdateTest\TestBase::class, ['"Title"' => 'Object 1']); $item = DataObject::get_one(SQLUpdateTest\TestBase::class, ['"Title"' => 'Object 1']);
$this->assertEquals('Description 1a', $item->Description); $this->assertEquals('Description 1a', $item->Description);
} }
public function testUpdateWithJoin()
{
$query = SQLUpdate::create()
->setTable('"SQLUpdateTestBase"')
->assign('"SQLUpdateTestBase"."Description"', 'Description 2a')
->addInnerJoin('SQLUpdateTestOther', '"SQLUpdateTestOther"."Description" = "SQLUpdateTestBase"."Description"');
$sql = $query->sql($parameters);
// Check SQL
$this->assertSQLEquals('UPDATE "SQLUpdateTestBase" INNER JOIN "SQLUpdateTestOther" ON "SQLUpdateTestOther"."Description" = "SQLUpdateTestBase"."Description" SET "SQLUpdateTestBase"."Description" = ?', $sql);
$this->assertEquals(['Description 2a'], $parameters);
// Check affected rows
$query->execute();
$this->assertEquals(1, DB::affected_rows());
// Check item updated
$item = DataObject::get_one(SQLUpdateTest\TestBase::class, ['"Title"' => 'Object 2']);
$this->assertEquals('Description 2a', $item->Description);
}
} }

View File

@ -10,3 +10,7 @@ SilverStripe\ORM\Tests\SQLUpdateTest\TestChild:
Title: 'Object 3' Title: 'Object 3'
Description: 'Description 3' Description: 'Description 3'
Details: 'Details 3' Details: 'Details 3'
SilverStripe\ORM\Tests\SQLUpdateTest\TestOther:
test3:
Title: 'Object 2 mirror'
Description: 'Description 2'

View File

@ -0,0 +1,16 @@
<?php
namespace SilverStripe\ORM\Tests\SQLUpdateTest;
use SilverStripe\Dev\TestOnly;
use SilverStripe\ORM\DataObject;
class TestOther extends DataObject implements TestOnly
{
private static $table_name = 'SQLUpdateTestOther';
private static $db = [
'Title' => 'Varchar(255)',
'Description' => 'Text'
];
}