[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

/wp-includes/ -> bookmark.php (source)

   1  <?php
   2  /**
   3   * Link/Bookmark API
   4   *
   5   * @package WordPress
   6   * @subpackage Bookmark
   7   */
   8  
   9  /**
  10   * Retrieve Bookmark data
  11   *
  12   * @since 2.1.0
  13   *
  14   * @global wpdb $wpdb WordPress database abstraction object.
  15   *
  16   * @param int|stdClass $bookmark
  17   * @param string       $output   Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which
  18   *                               correspond to an stdClass object, an associative array, or a numeric array,
  19   *                               respectively. Default OBJECT.
  20   * @param string       $filter   Optional. How to sanitize bookmark fields. Default 'raw'.
  21   * @return array|object|null Type returned depends on $output value.
  22   */
  23  function get_bookmark( $bookmark, $output = OBJECT, $filter = 'raw' ) {
  24      global $wpdb;
  25  
  26      if ( empty( $bookmark ) ) {
  27          if ( isset( $GLOBALS['link'] ) ) {
  28              $_bookmark = & $GLOBALS['link'];
  29          } else {
  30              $_bookmark = null;
  31          }
  32      } elseif ( is_object( $bookmark ) ) {
  33          wp_cache_add( $bookmark->link_id, $bookmark, 'bookmark' );
  34          $_bookmark = $bookmark;
  35      } else {
  36          if ( isset( $GLOBALS['link'] ) && ( $GLOBALS['link']->link_id == $bookmark ) ) {
  37              $_bookmark = & $GLOBALS['link'];
  38          } else {
  39              $_bookmark = wp_cache_get( $bookmark, 'bookmark' );
  40              if ( ! $_bookmark ) {
  41                  $_bookmark = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->links WHERE link_id = %d LIMIT 1", $bookmark ) );
  42                  if ( $_bookmark ) {
  43                      $_bookmark->link_category = array_unique( wp_get_object_terms( $_bookmark->link_id, 'link_category', array( 'fields' => 'ids' ) ) );
  44                      wp_cache_add( $_bookmark->link_id, $_bookmark, 'bookmark' );
  45                  }
  46              }
  47          }
  48      }
  49  
  50      if ( ! $_bookmark ) {
  51          return $_bookmark;
  52      }
  53  
  54      $_bookmark = sanitize_bookmark( $_bookmark, $filter );
  55  
  56      if ( OBJECT === $output ) {
  57          return $_bookmark;
  58      } elseif ( ARRAY_A === $output ) {
  59          return get_object_vars( $_bookmark );
  60      } elseif ( ARRAY_N === $output ) {
  61          return array_values( get_object_vars( $_bookmark ) );
  62      } else {
  63          return $_bookmark;
  64      }
  65  }
  66  
  67  /**
  68   * Retrieve single bookmark data item or field.
  69   *
  70   * @since 2.3.0
  71   *
  72   * @param string $field    The name of the data field to return.
  73   * @param int    $bookmark The bookmark ID to get field.
  74   * @param string $context  Optional. The context of how the field will be used.
  75   * @return string|WP_Error
  76   */
  77  function get_bookmark_field( $field, $bookmark, $context = 'display' ) {
  78      $bookmark = (int) $bookmark;
  79      $bookmark = get_bookmark( $bookmark );
  80  
  81      if ( is_wp_error( $bookmark ) ) {
  82          return $bookmark;
  83      }
  84  
  85      if ( ! is_object( $bookmark ) ) {
  86          return '';
  87      }
  88  
  89      if ( ! isset( $bookmark->$field ) ) {
  90          return '';
  91      }
  92  
  93      return sanitize_bookmark_field( $field, $bookmark->$field, $bookmark->link_id, $context );
  94  }
  95  
  96  /**
  97   * Retrieves the list of bookmarks
  98   *
  99   * Attempts to retrieve from the cache first based on MD5 hash of arguments. If
 100   * that fails, then the query will be built from the arguments and executed. The
 101   * results will be stored to the cache.
 102   *
 103   * @since 2.1.0
 104   *
 105   * @global wpdb $wpdb WordPress database abstraction object.
 106   *
 107   * @param string|array $args {
 108   *     Optional. String or array of arguments to retrieve bookmarks.
 109   *
 110   *     @type string   $orderby        How to order the links by. Accepts 'id', 'link_id', 'name', 'link_name',
 111   *                                    'url', 'link_url', 'visible', 'link_visible', 'rating', 'link_rating',
 112   *                                    'owner', 'link_owner', 'updated', 'link_updated', 'notes', 'link_notes',
 113   *                                    'description', 'link_description', 'length' and 'rand'.
 114   *                                    When `$orderby` is 'length', orders by the character length of
 115   *                                    'link_name'. Default 'name'.
 116   *     @type string   $order          Whether to order bookmarks in ascending or descending order.
 117   *                                    Accepts 'ASC' (ascending) or 'DESC' (descending). Default 'ASC'.
 118   *     @type int      $limit          Amount of bookmarks to display. Accepts any positive number or
 119   *                                    -1 for all.  Default -1.
 120   *     @type string   $category       Comma-separated list of category IDs to include links from.
 121   *                                    Default empty.
 122   *     @type string   $category_name  Category to retrieve links for by name. Default empty.
 123   *     @type int|bool $hide_invisible Whether to show or hide links marked as 'invisible'. Accepts
 124   *                                    1|true or 0|false. Default 1|true.
 125   *     @type int|bool $show_updated   Whether to display the time the bookmark was last updated.
 126   *                                    Accepts 1|true or 0|false. Default 0|false.
 127   *     @type string   $include        Comma-separated list of bookmark IDs to include. Default empty.
 128   *     @type string   $exclude        Comma-separated list of bookmark IDs to exclude. Default empty.
 129   *     @type string   $search         Search terms. Will be SQL-formatted with wildcards before and after
 130   *                                    and searched in 'link_url', 'link_name' and 'link_description'.
 131   *                                    Default empty.
 132   * }
 133   * @return object[] List of bookmark row objects.
 134   */
 135  function get_bookmarks( $args = '' ) {
 136      global $wpdb;
 137  
 138      $defaults = array(
 139          'orderby'        => 'name',
 140          'order'          => 'ASC',
 141          'limit'          => -1,
 142          'category'       => '',
 143          'category_name'  => '',
 144          'hide_invisible' => 1,
 145          'show_updated'   => 0,
 146          'include'        => '',
 147          'exclude'        => '',
 148          'search'         => '',
 149      );
 150  
 151      $parsed_args = wp_parse_args( $args, $defaults );
 152  
 153      $key   = md5( serialize( $parsed_args ) );
 154      $cache = wp_cache_get( 'get_bookmarks', 'bookmark' );
 155  
 156      if ( 'rand' !== $parsed_args['orderby'] && $cache ) {
 157          if ( is_array( $cache ) && isset( $cache[ $key ] ) ) {
 158              $bookmarks = $cache[ $key ];
 159              /**
 160               * Filters the returned list of bookmarks.
 161               *
 162               * The first time the hook is evaluated in this file, it returns the cached
 163               * bookmarks list. The second evaluation returns a cached bookmarks list if the
 164               * link category is passed but does not exist. The third evaluation returns
 165               * the full cached results.
 166               *
 167               * @since 2.1.0
 168               *
 169               * @see get_bookmarks()
 170               *
 171               * @param array $bookmarks   List of the cached bookmarks.
 172               * @param array $parsed_args An array of bookmark query arguments.
 173               */
 174              return apply_filters( 'get_bookmarks', $bookmarks, $parsed_args );
 175          }
 176      }
 177  
 178      if ( ! is_array( $cache ) ) {
 179          $cache = array();
 180      }
 181  
 182      $inclusions = '';
 183      if ( ! empty( $parsed_args['include'] ) ) {
 184          $parsed_args['exclude']       = '';  // Ignore exclude, category, and category_name params if using include.
 185          $parsed_args['category']      = '';
 186          $parsed_args['category_name'] = '';
 187  
 188          $inclinks = wp_parse_id_list( $parsed_args['include'] );
 189          if ( count( $inclinks ) ) {
 190              foreach ( $inclinks as $inclink ) {
 191                  if ( empty( $inclusions ) ) {
 192                      $inclusions = ' AND ( link_id = ' . $inclink . ' ';
 193                  } else {
 194                      $inclusions .= ' OR link_id = ' . $inclink . ' ';
 195                  }
 196              }
 197          }
 198      }
 199      if ( ! empty( $inclusions ) ) {
 200          $inclusions .= ')';
 201      }
 202  
 203      $exclusions = '';
 204      if ( ! empty( $parsed_args['exclude'] ) ) {
 205          $exlinks = wp_parse_id_list( $parsed_args['exclude'] );
 206          if ( count( $exlinks ) ) {
 207              foreach ( $exlinks as $exlink ) {
 208                  if ( empty( $exclusions ) ) {
 209                      $exclusions = ' AND ( link_id <> ' . $exlink . ' ';
 210                  } else {
 211                      $exclusions .= ' AND link_id <> ' . $exlink . ' ';
 212                  }
 213              }
 214          }
 215      }
 216      if ( ! empty( $exclusions ) ) {
 217          $exclusions .= ')';
 218      }
 219  
 220      if ( ! empty( $parsed_args['category_name'] ) ) {
 221          $parsed_args['category'] = get_term_by( 'name', $parsed_args['category_name'], 'link_category' );
 222          if ( $parsed_args['category'] ) {
 223              $parsed_args['category'] = $parsed_args['category']->term_id;
 224          } else {
 225              $cache[ $key ] = array();
 226              wp_cache_set( 'get_bookmarks', $cache, 'bookmark' );
 227              /** This filter is documented in wp-includes/bookmark.php */
 228              return apply_filters( 'get_bookmarks', array(), $parsed_args );
 229          }
 230      }
 231  
 232      $search = '';
 233      if ( ! empty( $parsed_args['search'] ) ) {
 234          $like   = '%' . $wpdb->esc_like( $parsed_args['search'] ) . '%';
 235          $search = $wpdb->prepare( ' AND ( (link_url LIKE %s) OR (link_name LIKE %s) OR (link_description LIKE %s) ) ', $like, $like, $like );
 236      }
 237  
 238      $category_query = '';
 239      $join           = '';
 240      if ( ! empty( $parsed_args['category'] ) ) {
 241          $incategories = wp_parse_id_list( $parsed_args['category'] );
 242          if ( count( $incategories ) ) {
 243              foreach ( $incategories as $incat ) {
 244                  if ( empty( $category_query ) ) {
 245                      $category_query = ' AND ( tt.term_id = ' . $incat . ' ';
 246                  } else {
 247                      $category_query .= ' OR tt.term_id = ' . $incat . ' ';
 248                  }
 249              }
 250          }
 251      }
 252      if ( ! empty( $category_query ) ) {
 253          $category_query .= ") AND taxonomy = 'link_category'";
 254          $join            = " INNER JOIN $wpdb->term_relationships AS tr ON ($wpdb->links.link_id = tr.object_id) INNER JOIN $wpdb->term_taxonomy as tt ON tt.term_taxonomy_id = tr.term_taxonomy_id";
 255      }
 256  
 257      if ( $parsed_args['show_updated'] ) {
 258          $recently_updated_test = ', IF (DATE_ADD(link_updated, INTERVAL 120 MINUTE) >= NOW(), 1,0) as recently_updated ';
 259      } else {
 260          $recently_updated_test = '';
 261      }
 262  
 263      $get_updated = ( $parsed_args['show_updated'] ) ? ', UNIX_TIMESTAMP(link_updated) AS link_updated_f ' : '';
 264  
 265      $orderby = strtolower( $parsed_args['orderby'] );
 266      $length  = '';
 267      switch ( $orderby ) {
 268          case 'length':
 269              $length = ', CHAR_LENGTH(link_name) AS length';
 270              break;
 271          case 'rand':
 272              $orderby = 'rand()';
 273              break;
 274          case 'link_id':
 275              $orderby = "$wpdb->links.link_id";
 276              break;
 277          default:
 278              $orderparams = array();
 279              $keys        = array( 'link_id', 'link_name', 'link_url', 'link_visible', 'link_rating', 'link_owner', 'link_updated', 'link_notes', 'link_description' );
 280              foreach ( explode( ',', $orderby ) as $ordparam ) {
 281                  $ordparam = trim( $ordparam );
 282  
 283                  if ( in_array( 'link_' . $ordparam, $keys, true ) ) {
 284                      $orderparams[] = 'link_' . $ordparam;
 285                  } elseif ( in_array( $ordparam, $keys, true ) ) {
 286                      $orderparams[] = $ordparam;
 287                  }
 288              }
 289              $orderby = implode( ',', $orderparams );
 290      }
 291  
 292      if ( empty( $orderby ) ) {
 293          $orderby = 'link_name';
 294      }
 295  
 296      $order = strtoupper( $parsed_args['order'] );
 297      if ( '' !== $order && ! in_array( $order, array( 'ASC', 'DESC' ), true ) ) {
 298          $order = 'ASC';
 299      }
 300  
 301      $visible = '';
 302      if ( $parsed_args['hide_invisible'] ) {
 303          $visible = "AND link_visible = 'Y'";
 304      }
 305  
 306      $query  = "SELECT * $length $recently_updated_test $get_updated FROM $wpdb->links $join WHERE 1=1 $visible $category_query";
 307      $query .= " $exclusions $inclusions $search";
 308      $query .= " ORDER BY $orderby $order";
 309      if ( -1 != $parsed_args['limit'] ) {
 310          $query .= ' LIMIT ' . $parsed_args['limit'];
 311      }
 312  
 313      $results = $wpdb->get_results( $query );
 314  
 315      if ( 'rand()' !== $orderby ) {
 316          $cache[ $key ] = $results;
 317          wp_cache_set( 'get_bookmarks', $cache, 'bookmark' );
 318      }
 319  
 320      /** This filter is documented in wp-includes/bookmark.php */
 321      return apply_filters( 'get_bookmarks', $results, $parsed_args );
 322  }
 323  
 324  /**
 325   * Sanitizes all bookmark fields.
 326   *
 327   * @since 2.3.0
 328   *
 329   * @param stdClass|array $bookmark Bookmark row.
 330   * @param string         $context  Optional. How to filter the fields. Default 'display'.
 331   * @return stdClass|array Same type as $bookmark but with fields sanitized.
 332   */
 333  function sanitize_bookmark( $bookmark, $context = 'display' ) {
 334      $fields = array(
 335          'link_id',
 336          'link_url',
 337          'link_name',
 338          'link_image',
 339          'link_target',
 340          'link_category',
 341          'link_description',
 342          'link_visible',
 343          'link_owner',
 344          'link_rating',
 345          'link_updated',
 346          'link_rel',
 347          'link_notes',
 348          'link_rss',
 349      );
 350  
 351      if ( is_object( $bookmark ) ) {
 352          $do_object = true;
 353          $link_id   = $bookmark->link_id;
 354      } else {
 355          $do_object = false;
 356          $link_id   = $bookmark['link_id'];
 357      }
 358  
 359      foreach ( $fields as $field ) {
 360          if ( $do_object ) {
 361              if ( isset( $bookmark->$field ) ) {
 362                  $bookmark->$field = sanitize_bookmark_field( $field, $bookmark->$field, $link_id, $context );
 363              }
 364          } else {
 365              if ( isset( $bookmark[ $field ] ) ) {
 366                  $bookmark[ $field ] = sanitize_bookmark_field( $field, $bookmark[ $field ], $link_id, $context );
 367              }
 368          }
 369      }
 370  
 371      return $bookmark;
 372  }
 373  
 374  /**
 375   * Sanitizes a bookmark field.
 376   *
 377   * Sanitizes the bookmark fields based on what the field name is. If the field
 378   * has a strict value set, then it will be tested for that, else a more generic
 379   * filtering is applied. After the more strict filter is applied, if the `$context`
 380   * is 'raw' then the value is immediately return.
 381   *
 382   * Hooks exist for the more generic cases. With the 'edit' context, the {@see 'edit_$field'}
 383   * filter will be called and passed the `$value` and `$bookmark_id` respectively.
 384   *
 385   * With the 'db' context, the {@see 'pre_$field'} filter is called and passed the value.
 386   * The 'display' context is the final context and has the `$field` has the filter name
 387   * and is passed the `$value`, `$bookmark_id`, and `$context`, respectively.
 388   *
 389   * @since 2.3.0
 390   *
 391   * @param string $field       The bookmark field.
 392   * @param mixed  $value       The bookmark field value.
 393   * @param int    $bookmark_id Bookmark ID.
 394   * @param string $context     How to filter the field value. Accepts 'raw', 'edit', 'db',
 395   *                            'display', 'attribute', or 'js'. Default 'display'.
 396   * @return mixed The filtered value.
 397   */
 398  function sanitize_bookmark_field( $field, $value, $bookmark_id, $context ) {
 399      $int_fields = array( 'link_id', 'link_rating' );
 400      if ( in_array( $field, $int_fields, true ) ) {
 401          $value = (int) $value;
 402      }
 403  
 404      switch ( $field ) {
 405          case 'link_category': // array( ints )
 406              $value = array_map( 'absint', (array) $value );
 407              // We return here so that the categories aren't filtered.
 408              // The 'link_category' filter is for the name of a link category, not an array of a link's link categories.
 409              return $value;
 410  
 411          case 'link_visible': // bool stored as Y|N
 412              $value = preg_replace( '/[^YNyn]/', '', $value );
 413              break;
 414          case 'link_target': // "enum"
 415              $targets = array( '_top', '_blank' );
 416              if ( ! in_array( $value, $targets, true ) ) {
 417                  $value = '';
 418              }
 419              break;
 420      }
 421  
 422      if ( 'raw' === $context ) {
 423          return $value;
 424      }
 425  
 426      if ( 'edit' === $context ) {
 427          /** This filter is documented in wp-includes/post.php */
 428          $value = apply_filters( "edit_{$field}", $value, $bookmark_id );
 429  
 430          if ( 'link_notes' === $field ) {
 431              $value = esc_html( $value ); // textarea_escaped
 432          } else {
 433              $value = esc_attr( $value );
 434          }
 435      } elseif ( 'db' === $context ) {
 436          /** This filter is documented in wp-includes/post.php */
 437          $value = apply_filters( "pre_{$field}", $value );
 438      } else {
 439          /** This filter is documented in wp-includes/post.php */
 440          $value = apply_filters( "{$field}", $value, $bookmark_id, $context );
 441  
 442          if ( 'attribute' === $context ) {
 443              $value = esc_attr( $value );
 444          } elseif ( 'js' === $context ) {
 445              $value = esc_js( $value );
 446          }
 447      }
 448  
 449      // Restore the type for integer fields after esc_attr().
 450      if ( in_array( $field, $int_fields, true ) ) {
 451          $value = (int) $value;
 452      }
 453  
 454      return $value;
 455  }
 456  
 457  /**
 458   * Deletes the bookmark cache.
 459   *
 460   * @since 2.7.0
 461   *
 462   * @param int $bookmark_id Bookmark ID.
 463   */
 464  function clean_bookmark_cache( $bookmark_id ) {
 465      wp_cache_delete( $bookmark_id, 'bookmark' );
 466      wp_cache_delete( 'get_bookmarks', 'bookmark' );
 467      clean_object_term_cache( $bookmark_id, 'link' );
 468  }


Generated: Sat Apr 20 01:00:03 2024 Cross-referenced by PHPXref 0.7.1