File: Sequence.php

package info (click to toggle)
matomo 5.8.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 95,068 kB
  • sloc: php: 289,425; xml: 127,249; javascript: 112,130; python: 202; sh: 178; makefile: 20; sql: 10
file content (130 lines) | stat: -rw-r--r-- 3,222 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
<?php

/**
 * Matomo - free/libre analytics platform
 *
 * @link    https://matomo.org
 * @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
 */

namespace Piwik;

use Exception;
use Piwik\Db\AdapterInterface;

/**
 * Used for generating auto increment ids.
 *
 * Example:
 *
 * $sequence = new Sequence('my_sequence_name');
 * $id = $sequence->getNextId();
 * $db->insert('anytable', array('id' => $id, '...' => '...'));
 */
class Sequence
{
    public const TABLE_NAME = 'sequence';
    /**
     * @var string
     */
    private $name;

    /**
     * @var AdapterInterface
     */
    private $db;

    /**
     * @var string
     */
    private $table;

    /**
     * The name of the table or sequence you want to get an id for.
     *
     * @param string $name eg 'archive_numeric_2014_11'
     * @param AdapterInterface $db You can optionally pass a DB adapter to make it work against another database.
     * @param string|null $tablePrefix
     */
    public function __construct($name, $db = null, $tablePrefix = null)
    {
        $this->name = $name;
        $this->db = $db ?: Db::get();
        $this->table = $this->getTableName($tablePrefix);
    }

    /**
     * Creates / initializes a new sequence.
     *
     * @param int $initialValue
     * @return int The actually used value to initialize the table.
     *
     * @throws \Exception in case a sequence having this name already exists.
     */
    public function create($initialValue = 0)
    {
        $initialValue = (int) $initialValue;

        $this->db->insert($this->table, array('name' => $this->name, 'value' => $initialValue));

        return $initialValue;
    }

    /**
     * Returns true if the sequence exist.
     *
     * @return bool
     */
    public function exists()
    {
        $query = $this->db->query('SELECT * FROM `' . $this->table . '` WHERE name = ?', $this->name);

        return $query->rowCount() > 0;
    }

    /**
     * Get / allocate / reserve a new id for the current sequence. Important: Getting the next id will fail in case
     * no such sequence exists. Make sure to create one if needed, see {@link create()}.
     *
     * @return int
     * @throws Exception
     */
    public function getNextId()
    {
        $sql   = 'UPDATE ' . $this->table . ' SET value = LAST_INSERT_ID(value + 1) WHERE name = ?';

        $result   = $this->db->query($sql, array($this->name));
        $rowCount = $result->rowCount();

        if (1 !== $rowCount) {
            throw new Exception("Sequence '" . $this->name . "' not found.");
        }

        $createdId = $this->db->lastInsertId();

        return (int) $createdId;
    }

    /**
     * Returns the current max id.
     * @return ?int
     * @internal
     */
    public function getCurrentId()
    {
        $sql   = 'SELECT value FROM `' . $this->table . '` WHERE name = ?';

        $id = $this->db->fetchOne($sql, array($this->name));

        if (!empty($id) || '0' === $id || 0 === $id) {
            return (int) $id;
        }

        return null;
    }

    private function getTableName($prefix)
    {
        return ($prefix !== null) ? $prefix . self::TABLE_NAME : Common::prefixTable(self::TABLE_NAME);
    }
}