[ Index ]

PHP Cross Reference of YOURLS

title

Body

[close]

/includes/ -> functions-shorturls.php (source)

   1  <?php
   2  /*
   3   * Functions relative to short URLs: adding, editing, etc
   4   * (either proper short URLs ("http://sho.rt/abc") or "keywords" (the "abc" part)
   5   */
   6  
   7  
   8  /**
   9   * Add a new link in the DB, either with custom keyword, or find one
  10   *
  11   * The return array will contain at least the following keys:
  12   *    status: string, 'success' or 'fail'
  13   *    message: string, a descriptive localized message of what happened in any case
  14   *    code: string, a short descriptivish and untranslated message describing what happened
  15   *    errorCode: string, a HTTP status code
  16   *    statusCode: string, a HTTP status code
  17   * Depending on the operation, it will contain any of the following keys:
  18   *    url: array, the short URL creation information, with keys: 'keyword', 'url', 'title', 'date', 'ip', 'clicks'
  19   *    title: string, the URL title
  20   *    shorturl: string, the proper short URL in full (eg 'http://sho.rt/abc')
  21   *    html: string, the HTML part used by the ajax to update the page display if any
  22   *
  23   * For compatibility with early consumers and third parties, when people asked for various data and data formats
  24   * before the internal API was really structured, the return array now collects several redundant information.
  25   *
  26   * @param  string $url      URL to shorten
  27   * @param  string $keyword  optional "keyword"
  28   * @param  string $title    option title
  29   * @param  int    $row_id   used to form unique IDs in the generated HTML
  30   * @return array            array with error/success state and short URL information
  31   */
  32  function yourls_add_new_link( $url, $keyword = '', $title = '', $row_id = 1 ) {
  33      // Allow plugins to short-circuit the whole function
  34      $pre = yourls_apply_filter( 'shunt_add_new_link', yourls_shunt_default(), $url, $keyword, $title );
  35      if ( yourls_shunt_default() !== $pre ) {
  36          return $pre;
  37      }
  38  
  39      /**
  40       * The result array.
  41       */
  42      $return = [
  43          // Always present :
  44          'status' => '',
  45          'code'   => '',
  46          'message' => '',
  47          'errorCode' => '',
  48          'statusCode' => '',
  49      ];
  50  
  51      // Sanitize URL
  52      $url = yourls_sanitize_url( $url );
  53      if ( !$url || $url == 'http://' || $url == 'https://' ) {
  54          $return['status']    = 'fail';
  55          $return['code']      = 'error:nourl';
  56          $return['message']   = yourls__( 'Missing or malformed URL' );
  57          $return['errorCode'] = $return['statusCode'] = '400'; // 400 Bad Request
  58  
  59          return yourls_apply_filter( 'add_new_link_fail_nourl', $return, $url, $keyword, $title );
  60      }
  61  
  62      // Prevent DB flood
  63      $ip = yourls_get_IP();
  64      yourls_check_IP_flood( $ip );
  65  
  66      // Prevent internal redirection loops: cannot shorten a shortened URL
  67      if (yourls_is_shorturl($url)) {
  68          $return['status']    = 'fail';
  69          $return['code']      = 'error:noloop';
  70          $return['message']   = yourls__( 'URL is a short URL' );
  71          $return['errorCode'] = $return['statusCode'] = '400'; // 400 Bad Request
  72          return yourls_apply_filter( 'add_new_link_fail_noloop', $return, $url, $keyword, $title );
  73      }
  74  
  75      yourls_do_action( 'pre_add_new_link', $url, $keyword, $title );
  76  
  77      // Check if URL was already stored and we don't accept duplicates
  78      if ( !yourls_allow_duplicate_longurls() && ($url_exists = yourls_long_url_exists( $url )) ) {
  79          yourls_do_action( 'add_new_link_already_stored', $url, $keyword, $title );
  80  
  81          $return['status']   = 'fail';
  82          $return['code']     = 'error:url';
  83          $return['url']      = array( 'keyword' => $url_exists->keyword, 'url' => $url, 'title' => $url_exists->title, 'date' => $url_exists->timestamp, 'ip' => $url_exists->ip, 'clicks' => $url_exists->clicks );
  84          $return['message']  = /* //translators: eg "http://someurl/ already exists (short URL: sho.rt/abc)" */ yourls_s('%s already exists in database (short URL: %s)',
  85              yourls_trim_long_string($url), preg_replace('!https?://!', '',  yourls_get_yourls_site()) . '/'. $url_exists->keyword );
  86          $return['title']    = $url_exists->title;
  87          $return['shorturl'] = yourls_link($url_exists->keyword);
  88          $return['errorCode'] = $return['statusCode'] = '409'; // 409 Conflict: the URL already exists, and the existing short URL is returned
  89  
  90          return yourls_apply_filter( 'add_new_link_already_stored_filter', $return, $url, $keyword, $title );
  91      }
  92  
  93      // Sanitize provided title, or fetch one
  94      if( isset( $title ) && !empty( $title ) ) {
  95          $title = yourls_sanitize_title( $title );
  96      } else {
  97          $title = yourls_get_remote_title( $url );
  98      }
  99      $title = yourls_apply_filter( 'add_new_title', $title, $url, $keyword );
 100  
 101      // Custom keyword provided : sanitize and make sure it's free
 102      if ($keyword) {
 103          yourls_do_action( 'add_new_link_custom_keyword', $url, $keyword, $title );
 104  
 105          $keyword = yourls_sanitize_keyword( $keyword, true );
 106          $keyword = yourls_apply_filter( 'custom_keyword', $keyword, $url, $title );
 107  
 108          if ( !yourls_keyword_is_free( $keyword ) ) {
 109              // This shorturl either reserved or taken already
 110              $return['status']  = 'fail';
 111              $return['code']    = 'error:keyword';
 112              $return['message'] = yourls_s( 'Short URL %s already exists in database or is reserved', $keyword );
 113              $return['errorCode'] = $return['statusCode'] = '400'; // 400 Bad Request
 114  
 115              return yourls_apply_filter( 'add_new_link_keyword_exists', $return, $url, $keyword, $title );
 116          }
 117  
 118          // Create random keyword
 119      } else {
 120          yourls_do_action( 'add_new_link_create_keyword', $url, $keyword, $title );
 121  
 122          $id = yourls_get_next_decimal();
 123  
 124          do {
 125              $keyword = yourls_int2string( $id );
 126              $keyword = yourls_apply_filter( 'random_keyword', $keyword, $url, $title );
 127              $id++;
 128          } while ( !yourls_keyword_is_free($keyword) );
 129  
 130          yourls_update_next_decimal($id);
 131      }
 132  
 133      // We should be all set now. Store the short URL !
 134  
 135      $timestamp = date( 'Y-m-d H:i:s' );
 136  
 137      try {
 138          if (yourls_insert_link_in_db( $url, $keyword, $title )){
 139              // everything ok, populate needed vars
 140              $return['url']      = array('keyword' => $keyword, 'url' => $url, 'title' => $title, 'date' => $timestamp, 'ip' => $ip );
 141              $return['status']   = 'success';
 142              $return['message']  = /* //translators: eg "http://someurl/ added to DB" */ yourls_s( '%s added to database', yourls_trim_long_string( $url ) );
 143              $return['title']    = $title;
 144              $return['html']     = yourls_table_add_row( $keyword, $url, $title, $ip, 0, time(), $row_id );
 145              $return['shorturl'] = yourls_link($keyword);
 146              $return['statusCode'] = '200'; // 200 OK
 147          } else {
 148              // unknown database error, couldn't store result
 149              $return['status']   = 'fail';
 150              $return['code']     = 'error:db';
 151              $return['message']  = yourls_s( 'Error saving url to database' );
 152              $return['errorCode'] = $return['statusCode'] = '500'; // 500 Internal Server Error
 153          }
 154      } catch (Exception $e) {
 155          // Keyword supposed to be free but the INSERT caused an exception: most likely we're facing a
 156          // concurrency problem. See Issue 2538.
 157          $return['status']  = 'fail';
 158          $return['code']    = 'error:concurrency';
 159          $return['message'] = $e->getMessage();
 160          $return['errorCode'] = $return['statusCode'] = '503'; // 503 Service Unavailable
 161      }
 162  
 163      yourls_do_action( 'post_add_new_link', $url, $keyword, $title, $return );
 164  
 165      return yourls_apply_filter( 'add_new_link', $return, $url, $keyword, $title );
 166  }
 167  /**
 168   * Get the keyword conversion base, as defined in config, filtered
 169   *
 170   * Expected values are 36 (lowercase + digits) or 62/64 (mixed case + digits).
 171   * Defaults to 36 when undefined or wrongly defined.
 172   *
 173   * @since 1.10.5
 174   * @return int Conversion base
 175   */
 176  function yourls_get_url_convert(): int {
 177      $convert = defined( 'YOURLS_URL_CONVERT' ) ? (int) YOURLS_URL_CONVERT : 36;
 178      return yourls_apply_filter( 'get_url_convert', $convert );
 179  }
 180  
 181  /**
 182   * Determine the allowed character set in short URLs
 183   *
 184   * @return string    Acceptable charset for short URLS keywords
 185   */
 186  function yourls_get_shorturl_charset() {
 187      if ( in_array( yourls_get_url_convert(), [ 62, 64 ] ) ) {
 188          $charset = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
 189      }
 190      else {
 191          // defined to 36, or wrongly defined
 192          $charset = '0123456789abcdefghijklmnopqrstuvwxyz';
 193      }
 194  
 195      return yourls_apply_filter( 'get_shorturl_charset', $charset );
 196  }
 197  
 198  /**
 199   * Is a URL a short URL? Accept either 'http://sho.rt/abc' or 'abc'
 200   *
 201   * @param  string $shorturl   short URL
 202   * @return bool               true if registered short URL, false otherwise
 203   */
 204  function yourls_is_shorturl( $shorturl ) {
 205      // TODO: make sure this function evolves with the feature set.
 206  
 207      $is_short = false;
 208  
 209      // Is $shorturl a URL (http://sho.rt/abc) or a keyword (abc) ?
 210      if( yourls_get_protocol( $shorturl ) ) {
 211          $keyword = yourls_get_relative_url( $shorturl );
 212      } else {
 213          $keyword = $shorturl;
 214      }
 215  
 216      // Check if it's a valid && used keyword
 217      if( $keyword && $keyword == yourls_sanitize_keyword( $keyword ) && yourls_keyword_is_taken( $keyword ) ) {
 218          $is_short = true;
 219      }
 220  
 221      return yourls_apply_filter( 'is_shorturl', $is_short, $shorturl );
 222  }
 223  
 224  /**
 225   * Get the list of reserved keywords for URLs.
 226   *
 227   * @return array             Array of reserved keywords
 228   */
 229  function yourls_get_reserved_URL() {
 230      global $yourls_reserved_URL;
 231      if ( ! isset( $yourls_reserved_URL ) || ! is_array( $yourls_reserved_URL ) ) {
 232          return array();
 233      }
 234  
 235      return $yourls_reserved_URL;
 236  }
 237  
 238  /**
 239   * Check to see if a given keyword is reserved (ie reserved URL or an existing page). Returns bool
 240   *
 241   * @param  string $keyword   Short URL keyword
 242   * @return bool              True if keyword reserved, false if free to be used
 243   */
 244  function yourls_keyword_is_reserved( $keyword ) {
 245      $keyword = yourls_sanitize_keyword( $keyword );
 246      $reserved = false;
 247  
 248      if ( in_array( $keyword, yourls_get_reserved_URL() )
 249          or yourls_is_page($keyword)
 250          or is_dir( YOURLS_ABSPATH ."/$keyword" )
 251      )
 252          $reserved = true;
 253  
 254      return yourls_apply_filter( 'keyword_is_reserved', $reserved, $keyword );
 255  }
 256  
 257  /**
 258   * Delete a link in the DB
 259   *
 260   * @param  string $keyword   Short URL keyword
 261   * @return int               Number of links deleted
 262   */
 263  function yourls_delete_link_by_keyword( $keyword ) {
 264      // Allow plugins to short-circuit the whole function
 265      $pre = yourls_apply_filter( 'shunt_delete_link_by_keyword', yourls_shunt_default(), $keyword );
 266      if ( yourls_shunt_default() !== $pre ) {
 267          return $pre;
 268      }
 269  
 270      $table = YOURLS_DB_TABLE_URL;
 271      $keyword = yourls_sanitize_keyword($keyword);
 272      $ydb = yourls_get_db('write-delete_link_by_keyword');
 273      $delete = $ydb->fetchAffected("DELETE FROM `$table` WHERE `keyword` = :keyword", array('keyword' => $keyword));
 274      $ydb->delete_infos($keyword); // Clear the cache.
 275      yourls_do_action( 'delete_link', $keyword, $delete );
 276      return $delete;
 277  }
 278  
 279  /**
 280   * SQL query to insert a new link in the DB. Returns boolean for success or failure of the inserting
 281   *
 282   * @param string $url
 283   * @param string $keyword
 284   * @param string $title
 285   * @return bool true if insert succeeded, false if failed
 286   */
 287  function yourls_insert_link_in_db($url, $keyword, $title = '' ) {
 288      $url       = yourls_sanitize_url($url);
 289      $keyword   = yourls_sanitize_keyword($keyword);
 290      $title     = yourls_sanitize_title($title);
 291      $timestamp = date('Y-m-d H:i:s');
 292      $ip        = yourls_get_IP();
 293  
 294      $table = YOURLS_DB_TABLE_URL;
 295      $binds = array(
 296          'keyword'   => $keyword,
 297          'url'       => $url,
 298          'title'     => $title,
 299          'timestamp' => $timestamp,
 300          'ip'        => $ip,
 301      );
 302      $ydb = yourls_get_db('write-insert_link_in_db');
 303      $insert = $ydb->fetchAffected("INSERT INTO `$table` (`keyword`, `url`, `title`, `timestamp`, `ip`, `clicks`) VALUES(:keyword, :url, :title, :timestamp, :ip, 0);", $binds);
 304  
 305      if ( $insert ) {
 306          $infos = $binds;
 307          $infos['clicks'] = 0;
 308          $ydb->set_infos($keyword, $infos);
 309      }
 310  
 311      yourls_do_action( 'insert_link', (bool)$insert, $url, $keyword, $title, $timestamp, $ip );
 312  
 313      return (bool)$insert;
 314  }
 315  
 316  /**
 317   * Check if a long URL already exists in the DB. Return NULL (doesn't exist) or an object with URL informations.
 318   *
 319   * This function supersedes function yourls_url_exists(), deprecated in 1.7.10, with a better naming.
 320   *
 321   * @since 1.7.10
 322   * @param  string $url  URL to check if already shortened
 323   * @return mixed        NULL if does not already exist in DB, or object with URL information as properties (eg keyword, url, title, ...)
 324   */
 325  function yourls_long_url_exists( $url ) {
 326      // Allow plugins to short-circuit the whole function
 327      $pre = yourls_apply_filter( 'shunt_url_exists', yourls_shunt_default(), $url );
 328      if ( yourls_shunt_default() !== $pre ) {
 329          return $pre;
 330      }
 331  
 332      $table = YOURLS_DB_TABLE_URL;
 333      $url   = yourls_sanitize_url($url);
 334      $url_exists = yourls_get_db('read-long_url_exists')->fetchObject("SELECT * FROM `$table` WHERE `url` = :url", array('url'=>$url));
 335  
 336      if ($url_exists === false) {
 337          $url_exists = NULL;
 338      }
 339  
 340      return yourls_apply_filter( 'url_exists', $url_exists, $url );
 341  }
 342  
 343  /**
 344   * Edit a link
 345   *
 346   * @param string $url
 347   * @param string $keyword
 348   * @param string $newkeyword
 349   * @param string $title
 350   * @return array Result of the edit and link information if successful
 351   */
 352  function yourls_edit_link($url, $keyword, $newkeyword='', $title='' ) {
 353      // Allow plugins to short-circuit the whole function
 354      $pre = yourls_apply_filter( 'shunt_edit_link', yourls_shunt_default(), $keyword, $url, $keyword, $newkeyword, $title );
 355      if ( yourls_shunt_default() !== $pre ) {
 356          return $pre;
 357      }
 358  
 359      $ydb = yourls_get_db('write-edit_link');
 360  
 361      $table = YOURLS_DB_TABLE_URL;
 362      $url = yourls_sanitize_url($url);
 363      $keyword = yourls_sanitize_keyword($keyword);
 364      $title = yourls_sanitize_title($title);
 365      $newkeyword = yourls_sanitize_keyword($newkeyword, true);
 366  
 367      if(!$url OR !$newkeyword) {
 368          $return['status']  = 'fail';
 369          $return['message'] = yourls__( 'Long URL or Short URL cannot be blank' );
 370          return yourls_apply_filter( 'edit_link', $return, $url, $keyword, $newkeyword, $title );
 371      }
 372  
 373      $old_url = $ydb->fetchValue("SELECT `url` FROM `$table` WHERE `keyword` = :keyword", array('keyword' => $keyword));
 374  
 375      // Check if new URL is not here already
 376      if ( $old_url != $url && !yourls_allow_duplicate_longurls() ) {
 377          $new_url_already_there = intval($ydb->fetchValue("SELECT COUNT(keyword) FROM `$table` WHERE `url` = :url;", array('url' => $url)));
 378      } else {
 379          $new_url_already_there = false;
 380      }
 381  
 382      // Check if the new keyword is not here already
 383      if ( $newkeyword != $keyword ) {
 384          $keyword_is_ok = yourls_keyword_is_free( $newkeyword );
 385      } else {
 386          $keyword_is_ok = true;
 387      }
 388  
 389      yourls_do_action( 'pre_edit_link', $url, $keyword, $newkeyword, $new_url_already_there, $keyword_is_ok );
 390  
 391      // All clear, update
 392      if ( ( !$new_url_already_there || yourls_allow_duplicate_longurls() ) && $keyword_is_ok ) {
 393              $sql   = "UPDATE `$table` SET `url` = :url, `keyword` = :newkeyword, `title` = :title WHERE `keyword` = :keyword";
 394              $binds = array('url' => $url, 'newkeyword' => $newkeyword, 'title' => $title, 'keyword' => $keyword);
 395              $update_url = $ydb->fetchAffected($sql, $binds);
 396          if( $update_url ) {
 397              $return['url']     = array( 'keyword'       => $newkeyword,
 398                                          'shorturl'      => yourls_link($newkeyword),
 399                                          'url'           => yourls_esc_url($url),
 400                                          'display_url'   => yourls_esc_html(yourls_trim_long_string($url)),
 401                                          'title'         => yourls_esc_attr($title),
 402                                          'display_title' => yourls_esc_html(yourls_trim_long_string( $title ))
 403                                  );
 404              $return['status']  = 'success';
 405              $return['message'] = yourls__( 'Link updated in database' );
 406              $ydb->update_infos_if_exists($newkeyword, array('url' => $url, 'title' => $title)); // Clear the cache.
 407              if ($keyword != $newkeyword) {
 408                  $ydb->delete_infos($keyword); // Clear the cache on the old keyword.
 409              }
 410          } else {
 411              $return['status']  = 'fail';
 412              $return['message'] = /* //translators: "Error updating http://someurl/ (Shorturl: http://sho.rt/blah)" */ yourls_s( 'Error updating %s (Short URL: %s)', yourls_esc_html(yourls_trim_long_string($url)), $keyword ) ;
 413          }
 414  
 415      // Nope
 416      } else {
 417          $return['status']  = 'fail';
 418          $return['message'] = yourls__( 'URL or keyword already exists in database' );
 419      }
 420  
 421      return yourls_apply_filter( 'edit_link', $return, $url, $keyword, $newkeyword, $title, $new_url_already_there, $keyword_is_ok );
 422  }
 423  
 424  /**
 425   * Update a title link (no checks for duplicates etc..)
 426   *
 427   * @param string $keyword
 428   * @param string $title
 429   * @return int number of rows updated
 430   */
 431  function yourls_edit_link_title( $keyword, $title ) {
 432      // Allow plugins to short-circuit the whole function
 433      $pre = yourls_apply_filter( 'shunt_edit_link_title', yourls_shunt_default(), $keyword, $title );
 434      if ( yourls_shunt_default() !== $pre ) {
 435          return $pre;
 436      }
 437  
 438      $keyword = yourls_sanitize_keyword( $keyword );
 439      $title = yourls_sanitize_title( $title );
 440  
 441      $table = YOURLS_DB_TABLE_URL;
 442      $ydb = yourls_get_db('write-edit_link_title');
 443      $update = $ydb->fetchAffected("UPDATE `$table` SET `title` = :title WHERE `keyword` = :keyword;", array('title' => $title, 'keyword' => $keyword));
 444  
 445      if ( $update ) {
 446          $ydb->update_infos_if_exists( $keyword, array('title' => $title) );
 447      }
 448  
 449      return $update;
 450  }
 451  
 452  /**
 453   * Check if keyword id is free (ie not already taken, and not reserved). Return bool.
 454   *
 455   * @param  string $keyword    short URL keyword
 456   * @return bool               true if keyword is taken (ie there is a short URL for it), false otherwise
 457   */
 458  function yourls_keyword_is_free( $keyword  ) {
 459      $free = true;
 460      if ( yourls_keyword_is_reserved( $keyword ) or yourls_keyword_is_taken( $keyword, false ) ) {
 461          $free = false;
 462      }
 463  
 464      return yourls_apply_filter( 'keyword_is_free', $free, $keyword );
 465  }
 466  
 467  /**
 468   * Check if a keyword matches a "page"
 469   *
 470   * @see https://docs.yourls.org/guide/extend/pages.html
 471   * @since 1.7.10
 472   * @param  string $keyword  Short URL $keyword
 473   * @return bool             true if is page, false otherwise
 474   */
 475  function yourls_is_page($keyword) {
 476      return yourls_apply_filter( 'is_page', file_exists( YOURLS_PAGEDIR . "/$keyword.php" ) );
 477  }
 478  
 479  /**
 480   * Check if a keyword is taken (ie there is already a short URL with this id). Return bool.
 481   *
 482   */
 483  /**
 484   * Check if a keyword is taken (ie there is already a short URL with this id). Return bool.
 485   *
 486   * @param  string $keyword    short URL keyword
 487   * @param  bool   $use_cache  optional, default true: do we want to use what is cached in memory, if any, or force a new SQL query
 488   * @return bool               true if keyword is taken (ie there is a short URL for it), false otherwise
 489   */
 490  function yourls_keyword_is_taken( $keyword, $use_cache = true ) {
 491      // Allow plugins to short-circuit the whole function
 492      $pre = yourls_apply_filter( 'shunt_keyword_is_taken', yourls_shunt_default(), $keyword );
 493      if ( yourls_shunt_default() !== $pre ) {
 494          return $pre;
 495      }
 496  
 497      $taken = false;
 498      // To check if a keyword is already associated with a short URL, we fetch all info matching that keyword. This
 499      // will save a query in case of a redirection in yourls-go.php because info will be cached
 500      if ( yourls_get_keyword_infos($keyword, $use_cache) ) {
 501          $taken = true;
 502      }
 503  
 504      return yourls_apply_filter( 'keyword_is_taken', $taken, $keyword );
 505  }
 506  
 507  /**
 508   * Return array of all information associated with keyword. Returns false if keyword not found. Set optional $use_cache to false to force fetching from DB
 509   *
 510   * Sincere apologies to native English speakers, we are aware that the plural of 'info' is actually 'info', not 'infos'.
 511   * This function yourls_get_keyword_infos() returns all information, while function yourls_get_keyword_info() (no 's') return only
 512   * one information. Blame YOURLS contributors whose mother tongue is not English :)
 513   *
 514   * @since 1.4
 515   * @param  string $keyword    Short URL keyword
 516   * @param  bool   $use_cache  Default true, set to false to force fetching from DB
 517   * @return false|object       false if not found, object with URL properties if found
 518   */
 519  function yourls_get_keyword_infos( $keyword, $use_cache = true ) {
 520      $ydb = yourls_get_db('read-get_keyword_infos');
 521      $keyword = yourls_sanitize_keyword( $keyword );
 522  
 523      yourls_do_action( 'pre_get_keyword', $keyword, $use_cache );
 524  
 525      if( $ydb->has_infos($keyword) && $use_cache === true ) {
 526          return yourls_apply_filter( 'get_keyword_infos', $ydb->get_infos($keyword), $keyword );
 527      }
 528  
 529      yourls_do_action( 'get_keyword_not_cached', $keyword );
 530  
 531      $table = YOURLS_DB_TABLE_URL;
 532      $infos = $ydb->fetchObject("SELECT * FROM `$table` WHERE `keyword` = :keyword", array('keyword' => $keyword));
 533  
 534      if( $infos ) {
 535          $infos = (array)$infos;
 536          $ydb->set_infos($keyword, $infos);
 537      } else {
 538          // is NULL if not found
 539          $infos = false;
 540          $ydb->set_infos($keyword, false);
 541      }
 542  
 543      return yourls_apply_filter( 'get_keyword_infos', $infos, $keyword );
 544  }
 545  
 546  /**
 547   * Return information associated with a keyword (eg clicks, URL, title...). Optional $notfound = string default message if nothing found
 548   *
 549   * @param string $keyword          Short URL keyword
 550   * @param string $field            Field to return (eg 'url', 'title', 'ip', 'clicks', 'timestamp', 'keyword')
 551   * @param false|string $notfound   Optional string to return if keyword not found
 552   * @return mixed|string
 553   */
 554  function yourls_get_keyword_info($keyword, $field, $notfound = false ) {
 555  
 556      // Allow plugins to short-circuit the whole function
 557      $pre = yourls_apply_filter( 'shunt_get_keyword_info', yourls_shunt_default(), $keyword, $field, $notfound );
 558      if ( yourls_shunt_default() !== $pre ) {
 559          return $pre;
 560      }
 561  
 562      $keyword = yourls_sanitize_keyword( $keyword );
 563      $infos = yourls_get_keyword_infos( $keyword );
 564  
 565      $return = $notfound;
 566      if ( isset( $infos[ $field ] ) && $infos[ $field ] !== false )
 567          $return = $infos[ $field ];
 568  
 569      return yourls_apply_filter( 'get_keyword_info', $return, $keyword, $field, $notfound );
 570  }
 571  
 572  /**
 573   * Return title associated with keyword. Optional $notfound = string default message if nothing found
 574   *
 575   * @param string $keyword          Short URL keyword
 576   * @param false|string $notfound   Optional string to return if keyword not found
 577   * @return mixed|string
 578   */
 579  function yourls_get_keyword_title( $keyword, $notfound = false ) {
 580      return yourls_get_keyword_info( $keyword, 'title', $notfound );
 581  }
 582  
 583  /**
 584   * Return long URL associated with keyword. Optional $notfound = string default message if nothing found
 585   *
 586   * @param string $keyword          Short URL keyword
 587   * @param false|string $notfound   Optional string to return if keyword not found
 588   * @return mixed|string
 589   */
 590  function yourls_get_keyword_longurl( $keyword, $notfound = false ) {
 591      return yourls_get_keyword_info( $keyword, 'url', $notfound );
 592  }
 593  
 594  /**
 595   * Return number of clicks on a keyword. Optional $notfound = string default message if nothing found
 596   *
 597   * @param string $keyword          Short URL keyword
 598   * @param false|string $notfound   Optional string to return if keyword not found
 599   * @return mixed|string
 600   */
 601  function yourls_get_keyword_clicks( $keyword, $notfound = false ) {
 602      return yourls_get_keyword_info( $keyword, 'clicks', $notfound );
 603  }
 604  
 605  /**
 606   * Return IP that added a keyword. Optional $notfound = string default message if nothing found
 607   *
 608   * @param string $keyword          Short URL keyword
 609   * @param false|string $notfound   Optional string to return if keyword not found
 610   * @return mixed|string
 611   */
 612  function yourls_get_keyword_IP( $keyword, $notfound = false ) {
 613      return yourls_get_keyword_info( $keyword, 'ip', $notfound );
 614  }
 615  
 616  /**
 617   * Return timestamp associated with a keyword. Optional $notfound = string default message if nothing found
 618   *
 619   * @param string $keyword          Short URL keyword
 620   * @param false|string $notfound   Optional string to return if keyword not found
 621   * @return mixed|string
 622   */
 623  function yourls_get_keyword_timestamp( $keyword, $notfound = false ) {
 624      return yourls_get_keyword_info( $keyword, 'timestamp', $notfound );
 625  }
 626  
 627  /**
 628   * Return array of stats for a given keyword
 629   *
 630   * This function supersedes function yourls_get_link_stats(), deprecated in 1.7.10, with a better naming.
 631   *
 632   * @since 1.7.10
 633   * @param  string $shorturl short URL keyword
 634   * @return array            stats
 635   */
 636  function yourls_get_keyword_stats( $shorturl ) {
 637      $table_url = YOURLS_DB_TABLE_URL;
 638      $shorturl  = yourls_sanitize_keyword( $shorturl );
 639  
 640      $res = yourls_get_db('read-get_keyword_stats')->fetchObject("SELECT * FROM `$table_url` WHERE `keyword` = :keyword", array('keyword' => $shorturl));
 641  
 642      if( !$res ) {
 643          // non existent link
 644          $return = array(
 645              'statusCode' => '404',
 646              'message'    => 'Error: short URL not found',
 647          );
 648      } else {
 649          $return = array(
 650              'statusCode' => '200',
 651              'message'    => 'success',
 652              'link'       => array(
 653                  'shorturl' => yourls_link($res->keyword),
 654                  'url'      => $res->url,
 655                  'title'    => $res->title,
 656                  'timestamp'=> $res->timestamp,
 657                  'ip'       => $res->ip,
 658                  'clicks'   => $res->clicks,
 659              )
 660          );
 661      }
 662  
 663      return yourls_apply_filter( 'get_link_stats', $return, $shorturl );
 664  }
 665  
 666  /**
 667   * Return array of keywords that redirect to the submitted long URL
 668   *
 669   * @since 1.7
 670   * @param string $longurl long url
 671   * @param string $order Optional SORT order (can be 'ASC' or 'DESC')
 672   * @return array array of keywords
 673   */
 674  function yourls_get_longurl_keywords( $longurl, $order = 'ASC' ) {
 675      $longurl = yourls_sanitize_url($longurl);
 676      $table   = YOURLS_DB_TABLE_URL;
 677      $sql     = "SELECT `keyword` FROM `$table` WHERE `url` = :url";
 678  
 679      if (in_array($order, array('ASC','DESC'))) {
 680          $sql .= " ORDER BY `keyword` ".$order;
 681      }
 682  
 683      return yourls_apply_filter( 'get_longurl_keywords', yourls_get_db('read-get_longurl_keywords')->fetchCol($sql, array('url'=>$longurl)), $longurl );
 684  }


Generated: Sun Jul 12 05:10:03 2026 Cross-referenced by PHPXref 0.7.1