Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion capone/class/caponemanager.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class CaponeManager extends FOGManagerController
*/
public function createSql()
{
return Schema::createTable(
return $this->createTableSql(
$this->tablename,
true,
[
Expand Down
2 changes: 1 addition & 1 deletion helloworld/class/helloworldmanager.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class HelloWorldManager extends FOGManagerController
*/
public function createSql()
{
return Schema::createTable(
return $this->createTableSql(
$this->tablename,
true,
[
Expand Down
2 changes: 1 addition & 1 deletion ldap/class/ldapgroupmanager.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class LDAPGroupManager extends FOGManagerController
*/
public function createSql()
{
return Schema::createTable(
return $this->createTableSql(
$this->tablename,
true,
[
Expand Down
2 changes: 1 addition & 1 deletion ldap/class/ldapgrouproleassociationmanager.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class LDAPGroupRoleAssociationManager extends FOGManagerController
*/
public function createSql()
{
return Schema::createTable(
return $this->createTableSql(
$this->tablename,
true,
[
Expand Down
2 changes: 1 addition & 1 deletion ldap/class/ldapgroupusergroupassociationmanager.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class LDAPGroupUserGroupAssociationManager extends FOGManagerController
*/
public function createSql()
{
return Schema::createTable(
return $this->createTableSql(
$this->tablename,
true,
[
Expand Down
2 changes: 1 addition & 1 deletion ldap/class/ldapmanager.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class LDAPManager extends FOGManagerController
*/
public function createSql()
{
return Schema::createTable(
return $this->createTableSql(
$this->tablename,
true,
[
Expand Down
2 changes: 1 addition & 1 deletion ldap/class/ldapusergrantmanager.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class LDAPUserGrantManager extends FOGManagerController
*/
public function createSql()
{
return Schema::createTable(
return $this->createTableSql(
$this->tablename,
true,
[
Expand Down
2 changes: 1 addition & 1 deletion location/class/locationassociationmanager.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class LocationAssociationManager extends FOGManagerController
*/
public function createSql()
{
return Schema::createTable(
return $this->createTableSql(
$this->tablename,
true,
[
Expand Down
2 changes: 1 addition & 1 deletion location/class/locationmanager.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class LocationManager extends FOGManagerController
*/
public function createSql()
{
return Schema::createTable(
return $this->createTableSql(
$this->tablename,
true,
[
Expand Down
2 changes: 1 addition & 1 deletion ntfy/class/ntfymanager.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public function createSql()
$keys = [
'nID'
];
return Schema::createTable(
return $this->createTableSql(
$this->tablename,
true,
$fields,
Expand Down
2 changes: 1 addition & 1 deletion oidc/class/oidcgroupmanager.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class OIDCGroupManager extends FOGManagerController
*/
public function createSql()
{
return Schema::createTable(
return $this->createTableSql(
$this->tablename,
true,
[
Expand Down
2 changes: 1 addition & 1 deletion oidc/class/oidcgrouproleassociationmanager.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class OIDCGroupRoleAssociationManager extends FOGManagerController
*/
public function createSql()
{
return Schema::createTable(
return $this->createTableSql(
$this->tablename,
true,
[
Expand Down
2 changes: 1 addition & 1 deletion oidc/class/oidcgroupusergroupassociationmanager.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class OIDCGroupUserGroupAssociationManager extends FOGManagerController
*/
public function createSql()
{
return Schema::createTable(
return $this->createTableSql(
$this->tablename,
true,
[
Expand Down
2 changes: 1 addition & 1 deletion oidc/class/oidcidentitymanager.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class OIDCIdentityManager extends FOGManagerController
*/
public function createSql()
{
return Schema::createTable(
return $this->createTableSql(
$this->tablename,
true,
[
Expand Down
2 changes: 1 addition & 1 deletion oidc/class/oidcmanager.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class OIDCManager extends FOGManagerController
*/
public function createSql()
{
return Schema::createTable(
return $this->createTableSql(
$this->tablename,
true,
[
Expand Down
2 changes: 1 addition & 1 deletion oidc/class/oidcusergrantmanager.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class OIDCUserGrantManager extends FOGManagerController
*/
public function createSql()
{
return Schema::createTable(
return $this->createTableSql(
$this->tablename,
true,
[
Expand Down
2 changes: 1 addition & 1 deletion ou/class/ouassociationmanager.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class OUAssociationManager extends FOGManagerController
*/
public function createSql()
{
return Schema::createTable(
return $this->createTableSql(
$this->tablename,
true,
[
Expand Down
2 changes: 1 addition & 1 deletion ou/class/oumanager.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class OUManager extends FOGManagerController
*/
public function createSql()
{
return Schema::createTable(
return $this->createTableSql(
$this->tablename,
true,
[
Expand Down
2 changes: 1 addition & 1 deletion pushbullet/class/pushbulletmanager.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public function createSql()
'pID',
'pToken'
];
return Schema::createTable(
return $this->createTableSql(
$this->tablename,
true,
$fields,
Expand Down
2 changes: 1 addition & 1 deletion slack/class/slackmanager.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class SlackManager extends FOGManagerController
*/
public function createSql()
{
return Schema::createTable(
return $this->createTableSql(
$this->tablename,
true,
[
Expand Down
2 changes: 1 addition & 1 deletion subnetgroup/class/subnetgroupmanager.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class SubnetGroupManager extends FOGManagerController
*/
public function createSql()
{
return Schema::createTable(
return $this->createTableSql(
$this->tablename,
true,
[
Expand Down
2 changes: 1 addition & 1 deletion tests/oidc-provider-safety.test.php
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ function () {
(new OIDCManager())->createSql();
$call = Schema::$lastCall;
if (count($call) < 7) {
fail('OIDCManager::createSql() did not call Schema::createTable()');
fail('OIDCManager::createSql() did not reach Schema::createTable()');
} else {
list(, , $cols, , , $defaults, $uniques) = $call;
$defaultFor = array_combine($cols, $defaults);
Expand Down
17 changes: 17 additions & 0 deletions tests/stubs/fog-stubs.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,23 @@ public function save()
*/
class FOGManagerController
{
/**
* Passes a createTable() call straight through.
*
* The real one (GH-1245) fills a default into every NOT NULL column that
* has none, leaving the primary key, anything the model declares
* required, and anything whose name ends in ID. It only ADDS -- a default
* the caller passed explicitly always wins -- so a pass-through here
* cannot mask an assertion about a default a manager sets deliberately,
* which is what these tests check. Reimplementing the rule in the stub
* would only give it somewhere to drift from.
*
* @return string
*/
public function createTableSql(...$args)
{
return Schema::createTable(...$args);
}
}

/**
Expand Down
147 changes: 147 additions & 0 deletions tests/tables-carry-column-defaults.test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
<?php
/**
* Every plugin must build its table through FOGManagerController's wrapper,
* so its optional columns get a DEFAULT.
*
* GH-1245. A column declared NOT NULL with no DEFAULT is only mandatory if
* something enforces it, and for nine years nothing did: PDODB cleared
* sql_mode on every connection, so the server downgraded the error to a
* warning and substituted an implicit zero. Removing the clear turned every
* one of those declarations into a real constraint, and an INSERT that omits
* one now fails with error 1364.
*
* FOG's schema step repairs the tables an install already has. It cannot
* repair a plugin's: createSql() runs as step 0 of the plugin's own schema(),
* so a plugin installed AFTER the migration gets a table built the old way --
* every optional column mandatory again.
*
* `$this->createTableSql()` (fogproject, FOGManagerController) fills a default
* into every NOT NULL column that has none, leaving bare only the primary
* key, anything the model declares required, and anything whose name ends in
* ID. `Schema::createTable()` does not: it is the raw builder underneath, and
* calling it directly is what leaves a table mandatory throughout. Measured
* against the live 1.6 install, the difference is 31 columns.
*
* So this is a one-line rule with a real consequence, and the failure is
* silent -- a plugin whose table is wrong looks fine until someone saves a
* record without filling in an optional field.
*
* PHP version 7.4+
*
* @category Tests
* @package FOGProject
* @author Tom Elliott <tommygunsster@gmail.com>
* @license http://opensource.org/licenses/gpl-3.0 GPLv3
* @link https://fogproject.org
*/

$root = dirname(__DIR__);
$failures = [];
$checks = 0;

/**
* Source with comments removed, so a commented-out call can neither satisfy
* a check nor fail one -- two managers mention Schema::createTable() in
* prose, explaining how it names its indexes.
*
* @param string $file the file to read
*
* @return string
*/
function tcStrip($file)
{
$clean = '';
foreach (token_get_all(file_get_contents($file)) as $token) {
if (is_array($token)
&& ($token[0] === T_COMMENT || $token[0] === T_DOC_COMMENT)
) {
continue;
}
$clean .= is_array($token) ? $token[1] : $token;
}

return $clean;
}

/**
* Records a check.
*
* @param bool $ok whether it passed
* @param string $message what failed, stated as the defect
*
* @return void
*/
function tcCheck($ok, $message)
{
global $checks, $failures;
$checks++;
if (!$ok) {
$failures[] = $message;
}
}

$managers = [];
$it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($root));
foreach ($it as $file) {
$path = $file->getPathname();
if (!preg_match('/manager\.class\.php$/', $file->getFilename())) {
continue;
}
if (false !== strpos($path, '/tests/')
|| false !== strpos($path, '/.git/')
) {
continue;
}
$managers[] = $path;
}
sort($managers);

$builders = 0;
foreach ($managers as $path) {
$src = tcStrip($path);
if (false === strpos($src, 'createTable(')
&& false === strpos($src, 'createTableSql(')
) {
continue;
}
$builders++;
$short = str_replace($root . '/', '', $path);
tcCheck(
false === strpos($src, 'Schema::createTable('),
sprintf(
'%s calls Schema::createTable() directly, so its table is built '
. 'with every optional column NOT NULL and no default. FOG\'s '
. 'schema step cannot repair it -- the table is created by this '
. 'plugin, after the step has run. Use $this->createTableSql(), '
. 'which takes the identical arguments.',
$short
)
);
tcCheck(
false !== strpos($src, 'createTableSql('),
sprintf(
'%s builds a table without going through createTableSql()',
$short
)
);
}

tcCheck(
$builders >= 20,
sprintf(
'only %d table-building managers were found, so the checks above '
. 'pass vacuously -- the scan did not reach the plugins',
$builders
)
);

if (count($failures)) {
fwrite(STDERR, 'FAIL (' . count($failures) . " of $checks):\n");
foreach ($failures as $f) {
fwrite(STDERR, " - $f\n");
}
exit(1);
}

echo "ok $checks checks passed\n";
exit(0);
2 changes: 1 addition & 1 deletion windowskey/class/windowskeyassociationmanager.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class WindowsKeyAssociationManager extends FOGManagerController
*/
public function createSql()
{
return Schema::createTable(
return $this->createTableSql(
$this->tablename,
true,
[
Expand Down
2 changes: 1 addition & 1 deletion windowskey/class/windowskeymanager.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class WindowsKeyManager extends FOGManagerController
*/
public function createSql()
{
return Schema::createTable(
return $this->createTableSql(
$this->tablename,
true,
[
Expand Down
2 changes: 1 addition & 1 deletion wolbroadcast/class/wolbroadcastmanager.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class WolbroadcastManager extends FOGManagerController
public function install()
{
$this->uninstall();
$sql = Schema::createTable(
$sql = $this->createTableSql(
$this->tablename,
true,
[
Expand Down