File: Adapter.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 (166 lines) | stat: -rw-r--r-- 4,924 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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
<?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\Db;

use Zend_Db_Table;
use Piwik\Piwik;

/**
 */
class Adapter
{
    /**
     * Create adapter
     *
     * @param string $adapterName database adapter name
     * @param array $dbInfos database connection info
     * @param bool $connect
     * @return AdapterInterface
     */
    public static function factory(
        $adapterName,
        #[\SensitiveParameter]
        &$dbInfos,
        $connect = true
    ) {
        if ($connect) {
            if (isset($dbInfos['port']) && is_string($dbInfos['port']) && $dbInfos['port'][0] === '/') {
                $dbInfos['unix_socket'] = $dbInfos['port'];
                unset($dbInfos['host']);
                unset($dbInfos['port']);
            }

            // not used by Zend Framework
            unset($dbInfos['tables_prefix']);
            unset($dbInfos['adapter']);
            unset($dbInfos['schema']);
        }

        $className = self::getAdapterClassName($adapterName);

        // make sure not to pass any references otherwise they will modify $dbInfos
        $infos = array();
        foreach ($dbInfos as $key => $val) {
            $infos[$key] = $val;
        }

        $adapter = new $className($infos);

        if ($connect) {
            try {
                $adapter->getConnection();

                Zend_Db_Table::setDefaultAdapter($adapter);
                // we don't want the connection information to appear in the logs
                $adapter->resetConfig();
            } catch (\Exception $e) {
                // we don't want certain exceptions to leak information
                $msg = self::overriddenExceptionMessage($e->getMessage());
                if ('' !== $msg) {
                    throw new \Exception($msg);
                }

                throw $e;
            }
        }

        return $adapter;
    }

    /**
     * Get adapter class name
     *
     * @param string $adapterName
     * @return string
     * @throws \Exception
     */
    private static function getAdapterClassName($adapterName)
    {
        $className = 'Piwik\Db\Adapter\\' . str_replace(' ', '\\', ucwords(str_replace(array('_', '\\'), ' ', strtolower($adapterName))));
        if (!class_exists($className)) {
            throw new \Exception(sprintf("Adapter '%s' is not valid. Maybe check that your Matomo configuration files in config/*.ini.php are readable by the webserver.", $adapterName));
        }
        return $className;
    }

    /**
     * Get default port for named adapter
     *
     * @deprecated use Schema::getDefaultPortForSchema instead
     * @param string $adapterName
     * @return int
     */
    public static function getDefaultPortForAdapter($adapterName)
    {
        $className = self::getAdapterClassName($adapterName);
        return call_user_func(array($className, 'getDefaultPort'));
    }

    /**
     * Get list of adapters
     *
     * @return array
     */
    public static function getAdapters()
    {
        static $adapterNames = array(
            // currently supported by Piwik
            'Pdo\Mysql',
            'Mysqli',

            // other adapters supported by Zend_Db
        );

        $adapters = array();

        foreach ($adapterNames as $adapterName) {
            $className = '\Piwik\Db\Adapter\\' . $adapterName;
            if (call_user_func(array($className, 'isEnabled'))) {
                $adapters[] = strtoupper($adapterName);
            }
        }

        return $adapters;
    }

    /**
     * Checks if the available adapters are recommended by Piwik or not.
     * @param string $adapterName
     * @return bool
     */
    public static function isRecommendedAdapter($adapterName)
    {
        return strtolower($adapterName) === 'pdo/mysql';
    }

    /**
     * Intercepts certain exception messages and replaces leaky ones with ones that don't reveal too much info
     * @param string $message
     * @return string
     */
    public static function overriddenExceptionMessage($message)
    {
        $safeMessageMap = array(
            // add any exception search terms and their replacement message here
            '[2006]'                        => Piwik::translate('General_ExceptionDatabaseUnavailable'),
            'MySQL server has gone away'    => Piwik::translate('General_ExceptionDatabaseUnavailable'),
            '[1698]'                        => Piwik::translate('General_ExceptionDatabaseAccess'),
            'Access denied'                 => Piwik::translate('General_ExceptionDatabaseAccess'),
        );

        foreach ($safeMessageMap as $search_term => $safeMessage) {
            if (strpos($message, $search_term) !== false) {
                return $safeMessage;
            }
        }

        return '';
    }
}