GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

CreateTableCommand::preExecute()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
namespace Rentgen\Schema\Manipulation;
3
4
use Rentgen\Schema\Command;
5
use Rentgen\Database\Table;
6
use Rentgen\Database\Column;
7
use Rentgen\Database\Column\CustomColumn;
8
use Rentgen\Database\Constraint\ForeignKey;
9
use Rentgen\Database\Constraint\PrimaryKey;
10
use Rentgen\Database\Constraint\Unique;
11
use Rentgen\Event\TableEvent;
12
use Rentgen\Schema\ColumnTypeMapper;
13
use Rentgen\Schema\Escapement;
14
15
class CreateTableCommand extends Command
16
{
17
    private $table;
18
19
    /**
20
     * Sets a table.
21
     *
22
     * @param Table $table The table instance.
23
     *
24
     * @return CreateTableCommand
25
     */
26
    public function setTable(Table $table)
27
    {
28
        $this->table = $table;
29
30
        return $this;
31
    }
32
33
    /**
34
     * {@inheritdoc}
35
     */
36
    public function getSql()
37
    {
38
        $escapement = new Escapement();
39
40
        $sql = sprintf('CREATE TABLE %s(%s);'
41
            , $escapement->escape($this->table->getQualifiedName())
42
            , $this->getColumnsSql() . $this->getConstraintsSql());
43
44
        $tableDescription = $this->table->getDescription();
45
        if (!empty($tableDescription)) {
46
        $sql .= sprintf("COMMENT ON TABLE %s IS '%s';",
47
            $escapement->escape($this->table->getQualifiedName()), $tableDescription);
48
        }
49
        $sql .= $this->getColumnComments();
50
51
        return $sql;
52
    }
53
54
    /**
55
     * Gets constraints query.
56
     *
57
     * @return string
58
     */
59
    private function getConstraintsSql()
60
    {
61
        $sql = '';
62
        foreach ($this->table->getConstraints() as $constraint) {
63
            $sql .= ',';
64
            if ($constraint instanceof PrimaryKey) {
65
                $sql .= (string) $constraint ;
66
            } elseif ($constraint instanceof ForeignKey) {
67
                $sql .= sprintf('CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s) MATCH SIMPLE ON UPDATE %s ON DELETE %s'
68
                    , $constraint->getName()
69
                    , implode(',', $constraint->getColumns())
70
                    , $constraint->getReferencedTable()->getQualifiedName()
71
                    , implode(',', $constraint->getReferencedColumns())
72
                    , $constraint->getUpdateAction()
73
                    , $constraint->getDeleteAction());
74
            } elseif ($constraint instanceof Unique) {
75
                $sql .= sprintf('CONSTRAINT %s UNIQUE (%s)'
76
                    , $constraint->getName()
77
                    , implode(',', $constraint->getColumns()));
78
            }
79
        }
80
81
        return rtrim($sql, ',');
82
    }
83
84
    /**
85
     * Gets columns query.
86
     *
87
     * @return string
88
     */
89
    private function getColumnsSql()
90
    {
91
        $columnTypeMapper = new ColumnTypeMapper();
92
93
        foreach ($this->table->getConstraints() as $constraint) {
94
            if ($constraint instanceof PrimaryKey) {
95
                $primaryKey = $constraint;
96
            }
97
        }
98
        if (!isset($primaryKey)) { // TODO find better solution
99
            $primaryKey = new PrimaryKey();
100
            $primaryKey->setTable($this->table);
101
            $this->table->addConstraint($primaryKey);
102
        }
103
104
        $sql = '';
105
        if (!$primaryKey->isMulti() && $primaryKey->isAutoCreateColumn()) {
106
            $sql = sprintf('%s %s NOT NULL,', $primaryKey->getColumns(), $primaryKey->isAutoIncrement() ? 'serial' : 'integer');
107
        }
108
        foreach ($this->table->getColumns() as $column) {
109
            if ($column instanceof CustomColumn) {
110
                $columnType = $column->getType();
111
            } else {
112
                $columnType = $columnTypeMapper->getNative($column->getType());
113
            }
114
115
            $sql .= sprintf('%s %s%s %s %s,'
116
                , $column->getName()
117
                , $columnType
118
                , $this->getTypeConstraints($column)
119
                , $column->isNotNull() ? 'NOT NULL' : ''
120
                , null === $column->getDefault() ? '' : 'DEFAULT'. ' ' . $this->addQuotesIfNeeded($column, $column->getDefault())
121
            );
122
        }
123
124
        return rtrim($sql, ',');
125
    }
126
127
    /**
128
     * Gets comments for columns.
129
     *
130
     * @return string
131
     */
132
    private function getColumnComments()
133
    {
134
        $escapement = new Escapement();
135
        $comments = '';
136
        foreach ($this->table->getColumns() as $column) {
137
             $columnDescription = $column->getDescription();
138
             if (!empty($columnDescription)) {
139
                $comments .= sprintf("COMMENT ON COLUMN %s.%s IS '%s';",
140
                    $escapement->escape($this->table->getQualifiedName()),
141
                    $escapement->escape($column->getName()),
142
                    $columnDescription);
143
             }
144
        }
145
146
        return $comments;
147
    }
148
149
150
    /**
151
     * {@inheritdoc}
152
     */
153
    protected function preExecute()
154
    {
155
        $this->dispatcher->dispatch('table.create', new TableEvent($this->table, $this->getSql()));
156
    }
157
158
    private function addQuotesIfNeeded(Column $column, $value)
159
    {
160
        return in_array($column->getType(), ['string', 'text']) ? sprintf("'%s'", $value) : $value;
161
    }
162
163
    private function getTypeConstraints(Column $column)
164
    {
165
        $typeConstraints = '';
166
        switch ($column->getType()) {
167
            case 'string':
168
                if ($column->getLimit()) {
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Rentgen\Database\Column as the method getLimit() does only exist in the following sub-classes of Rentgen\Database\Column: Rentgen\Database\Column\StringColumn. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
169
                    $typeConstraints = sprintf('(%s)', $column->getLimit());
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Rentgen\Database\Column as the method getLimit() does only exist in the following sub-classes of Rentgen\Database\Column: Rentgen\Database\Column\StringColumn. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
170
                }
171
                break;
172
            case 'decimal':
173
                if ($column->getPrecision()) {
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Rentgen\Database\Column as the method getPrecision() does only exist in the following sub-classes of Rentgen\Database\Column: Rentgen\Database\Column\DecimalColumn. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
174
                    $typeConstraints = sprintf('(%s, %s)', $column->getPrecision(), $column->getScale());
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Rentgen\Database\Column as the method getPrecision() does only exist in the following sub-classes of Rentgen\Database\Column: Rentgen\Database\Column\DecimalColumn. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Rentgen\Database\Column as the method getScale() does only exist in the following sub-classes of Rentgen\Database\Column: Rentgen\Database\Column\DecimalColumn. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
175
                }
176
                break;
177
        }
178
179
        return $typeConstraints;
180
    }
181
}
182