[ Index ]

PHP Cross Reference of YOURLS

title

Body

[close]

/includes/Database/ -> YDB.php (source)

   1  <?php
   2  
   3  /**
   4   * Aura SQL wrapper for YOURLS that creates the allmighty YDB object.
   5   *
   6   * A fine example of a "class that knows too much" (see https://en.wikipedia.org/wiki/God_object)
   7   *
   8   * Note to plugin authors: you most likely SHOULD NOT use directly methods and properties of this class. Use instead
   9   * function wrappers (eg don't use $ydb->option, or $ydb->set_option(), use yourls_*_options() functions instead).
  10   *
  11   * @since 1.7.3
  12   */
  13  
  14  namespace YOURLS\Database;
  15  
  16  use \Aura\Sql\ExtendedPdo;
  17  use \YOURLS\Database\Profiler;
  18  use \YOURLS\Database\Logger;
  19  use PDO;
  20  
  21  class YDB extends ExtendedPdo {
  22  
  23      /**
  24       * Debug mode, default false
  25       * @var bool
  26       */
  27      protected $debug = false;
  28  
  29      /**
  30       * Page context (ie "infos", "bookmark", "plugins"...)
  31       * @var string
  32       */
  33      protected $context = '';
  34  
  35      /**
  36       * Information related to a short URL keyword (eg timestamp, long URL, ...)
  37       *
  38       * @var array
  39       *
  40       */
  41      protected $infos = [];
  42  
  43      /**
  44       * Is YOURLS installed and ready to run?
  45       * @var bool
  46       */
  47      protected $installed = false;
  48  
  49      /**
  50       * Options
  51       * @var array
  52       */
  53      protected $option = [];
  54  
  55      /**
  56       * Plugin admin pages informations
  57       * @var array
  58       */
  59      protected $plugin_pages = [];
  60  
  61      /**
  62       * Plugin informations
  63       * @var array
  64       */
  65      protected $plugins = [];
  66  
  67      /**
  68       * Are we emulating prepare statements ?
  69       * @var bool
  70       */
  71      protected $is_emulate_prepare;
  72  
  73      /**
  74       * @since 1.7.3
  75       * @param string $dsn         The data source name
  76       * @param string $user        The username
  77       * @param string $pass        The password
  78       * @param array  $options     Driver-specific options
  79       * @param array  $attributes  Attributes to set after a connection
  80       */
  81      public function __construct($dsn, $user, $pass, $options, $attributes) {
  82          parent::__construct($dsn, $user, $pass, $options, $attributes);
  83      }
  84  
  85      /**
  86       * Init everything needed
  87       *
  88       * Everything we need to set up is done here in init(), not in the constructor, so even
  89       * when the connection fails (eg config error or DB dead), the constructor has worked
  90       * and we have a $ydb object properly instantiated (and for instance yourls_die() can
  91       * correctly die, even if using $ydb methods)
  92       *
  93       * @since  1.7.3
  94       * @return void
  95       */
  96      public function init() {
  97          $this->connect_to_DB();
  98  
  99          $this->set_emulate_state();
 100  
 101          $this->start_profiler();
 102      }
 103  
 104      /**
 105       * Check if we emulate prepare statements, and set bool flag accordingly
 106       *
 107       * Check if current driver can PDO::getAttribute(PDO::ATTR_EMULATE_PREPARES)
 108       * Some combinations of PHP/MySQL don't support this function. See
 109       * https://travis-ci.org/YOURLS/YOURLS/jobs/271423782#L481
 110       *
 111       * @since  1.7.3
 112       * @return void
 113       */
 114      public function set_emulate_state() {
 115          try {
 116              $this->is_emulate_prepare = $this->getAttribute(PDO::ATTR_EMULATE_PREPARES);
 117          } catch (\PDOException $e) {
 118              $this->is_emulate_prepare = false;
 119          }
 120      }
 121  
 122      /**
 123       * Get emulate status
 124       *
 125       * @since  1.7.3
 126       * @return bool
 127       */
 128      public function get_emulate_state() {
 129          return $this->is_emulate_prepare;
 130      }
 131  
 132      /**
 133       * Initiate real connection to DB server
 134       *
 135       * This is to check that the server is running and/or the config is OK
 136       *
 137       * @since  1.7.3
 138       * @return void
 139       * @throws \PDOException
 140       */
 141      public function connect_to_DB() {
 142          try {
 143              $this->connect();
 144          } catch ( \Exception $e ) {
 145              $this->dead_or_error($e);
 146          }
 147      }
 148  
 149      /**
 150       * Die with an error message
 151       *
 152       * @since  1.7.3
 153       *
 154       * @param \Exception $exception
 155       *
 156       * @return void
 157       */
 158      public function dead_or_error(\Exception $exception) {
 159          // Use any /user/db_error.php file
 160          $file = YOURLS_USERDIR . '/db_error.php';
 161          if(file_exists($file)) {
 162              if(yourls_include_file_sandbox( $file ) === true) {
 163                  die();
 164              }
 165          }
 166  
 167          $message  = yourls__( 'Incorrect DB config, or could not connect to DB' );
 168          $message .= '<br/>' . get_class($exception) .': ' . $exception->getMessage();
 169          yourls_die( yourls__( $message ), yourls__( 'Fatal error' ), 503 );
 170          die();
 171  
 172      }
 173  
 174      /**
 175       * Start a Message Logger
 176       *
 177       * @since  1.7.3
 178       * @see    \Aura\Sql\Profiler\Profiler
 179       * @see    \Aura\Sql\Profiler\MemoryLogger
 180       * @return void
 181       */
 182      public function start_profiler() {
 183          // Instantiate a custom logger and make it the profiler
 184          $yourls_logger = new Logger();
 185          $profiler = new Profiler($yourls_logger);
 186          $this->setProfiler($profiler);
 187  
 188          /* By default, make "query" the log level. This way, each internal logging triggered
 189           * by Aura SQL will be a "query", and logging triggered by yourls_debug() will be
 190           * a "message". See includes/functions-debug.php:yourls_debug()
 191           */
 192          $profiler->setLoglevel('query');
 193      }
 194  
 195      /**
 196       * @param string $context
 197       * @return void
 198       */
 199      public function set_html_context($context) {
 200          $this->context = $context;
 201      }
 202  
 203      /**
 204       * @return string
 205       */
 206      public function get_html_context() {
 207          return $this->context;
 208      }
 209  
 210      // Options low level functions, see \YOURLS\Database\Options
 211  
 212      /**
 213       * @param string $name
 214       * @param mixed  $value
 215       * @return void
 216       */
 217      public function set_option($name, $value) {
 218          $this->option[$name] = $value;
 219      }
 220  
 221      /**
 222       * @param  string $name
 223       * @return bool
 224       */
 225      public function has_option($name) {
 226          return array_key_exists($name, $this->option);
 227      }
 228  
 229      /**
 230       * @param  string $name
 231       * @return string
 232       */
 233      public function get_option($name) {
 234          return $this->option[$name];
 235      }
 236  
 237      /**
 238       * @param string $name
 239       * @return void
 240       */
 241      public function delete_option($name) {
 242          unset($this->option[$name]);
 243      }
 244  
 245  
 246      // Infos (related to keyword) low level functions
 247  
 248      /**
 249       * @param string $keyword
 250       * @param mixed  $infos
 251       * @return void
 252       */
 253      public function set_infos($keyword, $infos) {
 254          $this->infos[$keyword] = $infos;
 255      }
 256  
 257      /**
 258       * @param  string $keyword
 259       * @return bool
 260       */
 261      public function has_infos($keyword) {
 262          return array_key_exists($keyword, $this->infos);
 263      }
 264  
 265      /**
 266       * @param  string $keyword
 267       * @return array
 268       */
 269      public function get_infos($keyword) {
 270          return $this->infos[$keyword];
 271      }
 272  
 273      /**
 274       * @param string $keyword
 275       * @return void
 276       */
 277      public function delete_infos($keyword) {
 278          unset($this->infos[$keyword]);
 279      }
 280  
 281      /**
 282       * @todo: infos & options are working the same way here. Abstract this.
 283       */
 284  
 285  
 286      // Plugin low level functions, see functions-plugins.php
 287  
 288      /**
 289       * @return array
 290       */
 291      public function get_plugins() {
 292          return $this->plugins;
 293      }
 294  
 295      /**
 296       * @param array $plugins
 297       * @return void
 298       */
 299      public function set_plugins(array $plugins) {
 300          $this->plugins = $plugins;
 301      }
 302  
 303      /**
 304       * @param string $plugin  plugin filename
 305       * @return void
 306       */
 307      public function add_plugin($plugin) {
 308          $this->plugins[] = $plugin;
 309      }
 310  
 311      /**
 312       * @param string $plugin  plugin filename
 313       * @return void
 314       */
 315      public function remove_plugin($plugin) {
 316          unset($this->plugins[$plugin]);
 317      }
 318  
 319  
 320      // Plugin Pages low level functions, see functions-plugins.php
 321  
 322      /**
 323       * @return array
 324       */
 325      public function get_plugin_pages() {
 326          return is_array( $this->plugin_pages ) ? $this->plugin_pages : [];
 327      }
 328  
 329      /**
 330       * @param array $pages
 331       * @return void
 332       */
 333      public function set_plugin_pages(array $pages) {
 334          $this->plugin_pages = $pages;
 335      }
 336  
 337      /**
 338       * @param string   $slug
 339       * @param string   $title
 340       * @param callable $function
 341       * @return void
 342       */
 343      public function add_plugin_page( $slug, $title, $function ) {
 344          $this->plugin_pages[ $slug ] = [
 345              'slug'     => $slug,
 346              'title'    => $title,
 347              'function' => $function,
 348          ];
 349      }
 350  
 351      /**
 352       * @param string $slug
 353       * @return void
 354       */
 355      public function remove_plugin_page( $slug ) {
 356          unset( $this->plugin_pages[ $slug ] );
 357      }
 358  
 359  
 360      /**
 361       * Return count of SQL queries performed
 362       *
 363       * @since  1.7.3
 364       * @return int
 365       */
 366      public function get_num_queries() {
 367          return count( (array) $this->get_queries() );
 368      }
 369  
 370      /**
 371       * Return SQL queries performed
 372       *
 373       * @since  1.7.3
 374       * @return array
 375       */
 376      public function get_queries() {
 377          $queries = $this->getProfiler()->getLogger()->getMessages();
 378  
 379          // Only keep messages that start with "SQL "
 380          $queries = array_filter($queries, function($query) {return substr( $query, 0, 4 ) === "SQL ";});
 381  
 382          return $queries;
 383      }
 384  
 385      /**
 386       * Set YOURLS installed state
 387       *
 388       * @since  1.7.3
 389       * @param  bool $bool
 390       * @return void
 391       */
 392      public function set_installed($bool) {
 393          $this->installed = $bool;
 394      }
 395  
 396      /**
 397       * Get YOURLS installed state
 398       *
 399       * @since  1.7.3
 400       * @return bool
 401       */
 402      public function is_installed() {
 403          return $this->installed;
 404      }
 405  
 406      /**
 407       * Return standardized DB version
 408       *
 409       * The regex removes everything that's not a number at the start of the string, or remove anything that's not a number and what
 410       * follows after that.
 411       *   'omgmysql-5.5-ubuntu-4.20' => '5.5'
 412       *   'mysql5.5-ubuntu-4.20'     => '5.5'
 413       *   '5.5-ubuntu-4.20'          => '5.5'
 414       *   '5.5-beta2'                => '5.5'
 415       *   '5.5'                      => '5.5'
 416       *
 417       * @since  1.7.3
 418       * @return string
 419       */
 420      public function mysql_version() {
 421          $version = $this->pdo->getAttribute(PDO::ATTR_SERVER_VERSION);
 422          return $version;
 423      }
 424  
 425  }


Generated: Tue Jan 21 05:10:11 2025 Cross-referenced by PHPXref 0.7.1