delete( $table, array( 'entry_id' => $entry_id ), array( '%d' ) ); foreach ( $tags as $tag ) { // IGNORE: the database may treat two spellings as the same tag (for example "Café" and "cafe"). $wpdb->query( $wpdb->prepare( 'INSERT IGNORE INTO %i (entry_id, tag) VALUES (%d, %s)', $table, $entry_id, $tag ) ); } return self::for_entries( array( $entry_id ) )[ $entry_id ] ?? array(); } /** * Tags of several entries: entry ID => tags (alphabetical, ignoring case). * * @param int[] $ids Entry IDs. * @return array */ public static function for_entries( array $ids ): array { global $wpdb; $ids = array_values( array_filter( array_map( 'intval', $ids ) ) ); if ( array() === $ids ) { return array(); } $placeholders = implode( ',', array_fill( 0, count( $ids ), '%d' ) ); // $placeholders is a list of %d markers; all values are bound by prepare(). // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare, WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber $rows = $wpdb->get_results( $wpdb->prepare( "SELECT entry_id, tag FROM %i WHERE entry_id IN ({$placeholders})", array_merge( array( Database::table( 'entry_tags' ) ), $ids ) ) ); $out = array(); foreach ( (array) $rows as $row ) { $out[ (int) $row->entry_id ][] = (string) $row->tag; } return array_map( static function ( array $tags ): array { usort( $tags, 'strnatcasecmp' ); return $tags; }, $out ); } /** * Every tag in use with its number of entries, alphabetical (ignoring case). * * @param int $limit Max tags. * @return array */ public static function all( int $limit = 200 ): array { global $wpdb; $rows = $wpdb->get_results( $wpdb->prepare( 'SELECT tag, COUNT(*) AS total FROM %i GROUP BY tag ORDER BY tag LIMIT %d', Database::table( 'entry_tags' ), $limit ) ); $out = array(); foreach ( (array) $rows as $row ) { $out[ (string) $row->tag ] = (int) $row->total; } uksort( $out, 'strnatcasecmp' ); return $out; } /** * Removes an entry's tags (when the entry is deleted). * * @param int $entry_id Entry ID. */ public static function delete_for_entry( int $entry_id ): void { global $wpdb; $wpdb->delete( Database::table( 'entry_tags' ), array( 'entry_id' => $entry_id ), array( '%d' ) ); } }