Файловый менеджер - Редактировать - /var/www/xthruster/html/wp-content/plugins/elementor-pro/modules/notes/database/query/note-query-builder.php
Назад
<?php namespace ElementorPro\Modules\Notes\Database\Query; use Elementor\Core\Utils\Collection; use ElementorPro\Core\Database\Join_Clause; use ElementorPro\Modules\Notes\User\Capabilities; use ElementorPro\Core\Database\Model_Query_Builder; use ElementorPro\Core\Database\Query_Builder; use ElementorPro\Modules\Notes\Database\Models\Note; use ElementorPro\Modules\Notes\Database\Models\User; use ElementorPro\Modules\Notes\Module; use ElementorPro\Modules\Notes\Database\Models\Document; use Elementor\Core\Base\Document as BaseDocument; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } /** * @method Note|null first() * @method Note|null find( $id, $field = 'id' ) */ class Note_Query_Builder extends Model_Query_Builder { /** * Determine if the query should include trashed notes. * * @var bool */ private $with_trashed = false; /** * Note_Query_Builder constructor. * * @param \wpdb|null $connection */ public function __construct( \wpdb $connection = null ) { parent::__construct( Note::class, $connection ); } /** * Override the default `compile_wheres()` to handle `with_trashed()`. * * @inheritDoc */ public function compile_wheres() { // Don't show trashed notes. // TODO: Should be called before `get()`, `update()`, `delete()` using `apply_scopes()`. if ( ! $this->with_trashed ) { $this->where( 'status', '!=', Note::STATUS_TRASH ); } return parent::compile_wheres(); } /** * Set the `with_trashed` flag to `true`. * * @return $this */ public function with_trashed() { $this->with_trashed = true; return $this; } /** * Eager load the Note's replies. * * @param callable|null $callback - Callback that gets a `Note_Query_Builder` to customize the replies query. * * @return $this */ public function with_replies( callable $callback = null ) { $key = 'replies'; $foreign_key = 'parent_id'; $local_key = 'id'; $builder = Note::query(); return $this->add_with( $key, function ( Collection $notes ) use ( $callback, $key, $foreign_key, $local_key, $builder ) { // Get all the replies. $replies = $builder ->where_in( $foreign_key, $notes->pluck( $local_key )->all() ) ->when( $callback, function ( Note_Query_Builder $q, callable $callback ) { // Execute any user-defined callback. // Used to extend the query (e.g. add another `where` or eager load relations). call_user_func( $callback, $q ); } ) ->get() ->group_by( $foreign_key ); // Group the replies by their thread. // Add the replies to each Note object. return $notes->map( function ( $note ) use ( $replies, $key, $local_key ) { $note[ $key ] = $replies->get( $note[ $local_key ], [] ); return $note; } ); } ); } /** * Eager load the Note's replies count. * * @return $this */ public function with_replies_count() { return $this->add_sub_select( function ( Query_Builder $q ) { $q->from( Module::TABLE_NOTES, 'replies' ) ->select( [ 'replies.id' ], static::COLUMN_COUNT ) ->where_column( 'replies.parent_id', '=', Module::TABLE_NOTES . '.id' ); }, 'replies_count' ); } /** * Eager load the Note's readers. * * @return $this */ public function with_readers() { return $this->add_with( 'readers', function ( Collection $notes ) { $ids = $notes->pluck( 'id' )->all(); // Get all relations. $pivot = ( new Query_Builder() ) ->from( Module::TABLE_NOTES_USERS_RELATIONS ) ->select( [ 'note_id', 'user_id' ] ) ->where( 'type', '=', Note::USER_RELATION_READ ) ->where_in( 'note_id', $ids ) ->get(); $ids = $pivot->pluck( 'user_id' )->all(); // Exit if there are no readers. if ( empty( $ids ) ) { return $notes; } // Get all users that are associated with the relations, and map them into `$user_id => User`. $readers = User::query() ->where_in( 'ID', $ids ) ->get() ->key_by( 'ID' ); // Attach a user to each pivot row & group by note id. $pivot = $pivot->map( function ( $item ) use ( $readers ) { $item['user'] = $readers->get( $item['user_id'], [] ); return $item; } )->filter( function ( $item ) { // Make sure that relations with non-existing users won't be returned. return ! empty( $item['user'] ); } )->group_by( 'note_id' ); // Add the readers to the note. return $notes->map( function ( $note ) use ( $pivot ) { $users = $pivot->get( $note['id'], [] ); $readers = ( new Collection( $users ) ) ->unique( 'user_id' ) ->pluck( 'user' ) ->all(); $note['readers'] = $readers; return $note; } ); } ); } /** * Eager load the Note's author. * * @return $this */ public function with_author() { return $this->add_with( 'author', function ( Collection $notes ) { $ids = $notes ->pluck( 'author_id' ) ->unique() ->values(); $authors = User::query() ->where_in( 'ID', $ids ) ->get() ->key_by( 'ID' ); return $notes->map( function ( $note ) use ( $authors ) { $note['author'] = $authors->get( $note['author_id'] ); return $note; } ); } ); } /** * Eager load the Note's document. * * @return $this */ public function with_document() { return $this->add_with( 'document', function ( Collection $notes ) { $ids = $notes ->pluck( 'post_id' ) ->unique() ->values(); $documents = Document::query() ->where_in( 'ID', $ids ) ->get() ->key_by( 'ID' ); return $notes->map( function ( $note ) use ( $documents ) { $note['document'] = $documents->get( $note['post_id'] ); return $note; } ); } ); } /** * Eager load the Note's read state by a user ID. * * @param int $user_id - User ID to check. * * @return $this */ public function with_is_read( $user_id ) { $alias = 'is_read'; if ( $this->is_column_selected( $alias ) ) { return $this; } // TODO: Maybe use JOIN. return $this->add_sub_select( function ( Query_Builder $q ) use ( $user_id ) { $q->from( Module::TABLE_NOTES_USERS_RELATIONS, 'users_relations' ) ->select( [ 'users_relations.id' ], static::COLUMN_COUNT ) ->where( 'type', '=', Note::USER_RELATION_READ ) ->where_column( Module::TABLE_NOTES . '.id', '=', 'users_relations.note_id' ) ->where( 'user_id', '=', $user_id ); }, $alias ); } /** * Make sure that users without permissions to read private notes won't get them. * * @param integer $user_id - User ID to check. * * @return Note_Query_Builder */ public function only_visible( $user_id ) { // User can read private notes - do nothing. if ( user_can( $user_id, Capabilities::READ_OTHERS_PRIVATE_NOTES ) ) { return $this; } // User can read only public or their note. return $this->where( function ( Query_Builder $q ) use ( $user_id ) { $q->where( 'is_public', '=', true ) ->or_where( 'author_id', '=', $user_id ); } ); } /** * Filter only notes that their post is visible to the user. * * @param $user_id * * @return $this */ public function only_visible_posts( $user_id ) { $post_types = ( new Collection( get_post_types() ) ) ->map( function ( $post_type_value ) { return get_post_type_object( $post_type_value ); } ); $can_read_unpublished_post_types = $post_types ->filter( function ( $post_type ) use ( $user_id ) { return $post_type && user_can( $user_id, $post_type->cap->edit_posts ); } ) ->keys(); $can_read_private_post_types = $post_types ->filter( function ( $post_type ) use ( $user_id ) { return $post_type && user_can( $user_id, $post_type->cap->read_private_posts ); } ) ->keys(); foreach ( [ 'route_post_id', 'post_id' ] as $column ) { $table_alias = "posts_{$column}_visible"; $this ->left_join( function ( Join_Clause $join ) use ( $table_alias, $column ) { return $join->table( 'posts', $table_alias ) ->on_column( "{$table_alias}.ID", '=', $column ); } ) ->where( function ( Query_Builder $query ) use ( $can_read_unpublished_post_types, $table_alias ) { // If there is no post ID, there is nothing to check, // OR if the post is published the user can view the post, // OR if the user is allowed to view unpublished post (for the current `post_type`). $query->where_null( "{$table_alias}.ID" ) ->or_where( "{$table_alias}.post_status", '=', BaseDocument::STATUS_PUBLISH ) ->or_where_in( "{$table_alias}.post_type", $can_read_unpublished_post_types ); } ) ->where( function ( Query_Builder $query ) use ( $user_id, $can_read_private_post_types, $table_alias ) { // If there is no post ID, there is nothing to check, // OR if the post is not private the user can see view post, // OR if the current user is the author of the private post, so he can view the post, // OR if the user is allowed to view private posts (for the current `post_type`). $query->where_null( "{$table_alias}.ID" ) ->or_where( "{$table_alias}.post_status", '!=', BaseDocument::STATUS_PRIVATE ) ->or_where( "{$table_alias}.post_author", '=', $user_id ) ->or_where_in( "{$table_alias}.post_type", $can_read_private_post_types ); } ); } return $this; } /** * Filter only the notes that are relevant to the user. * * @param int $user_id - User ID to check. * * @return Note_Query_Builder */ public function only_relevant( $user_id ) { // User replied to the thread. $replied_to_thread = function ( Query_Builder $q ) use ( $user_id ) { $q->select_raw( [ 1 ] ) ->from( Module::TABLE_NOTES, 'e_notes_relevant_replies' ) ->where_column( 'e_notes_relevant_replies.parent_id', '=', Module::TABLE_NOTES . '.id' ) ->where( 'e_notes_relevant_replies.author_id', '=', $user_id ) ->where( 'e_notes_relevant_replies.status', '!=', Note::STATUS_TRASH ); }; // User is mentioned in the thread. $mentioned_in_thread = function ( Query_Builder $q ) use ( $user_id ) { $q->select_raw( [ 1 ] ) ->table( Module::TABLE_NOTES_USERS_RELATIONS, 'e_notes_relevant_relation' ) ->where_column( 'e_notes_relevant_relation.note_id', '=', Module::TABLE_NOTES . '.id' ) ->where( 'e_notes_relevant_relation.user_id', '=', $user_id ) ->where( 'e_notes_relevant_relation.type', '=', Note::USER_RELATION_MENTION ); }; // User is mentioned in one of the replies. $mentioned_in_replies = function ( Query_Builder $q ) use ( $user_id ) { $q->select_raw( [ 1 ] ) ->table( Module::TABLE_NOTES_USERS_RELATIONS, 'e_notes_relevant_relation_replies' ) ->where_in( 'e_notes_relevant_relation_replies.note_id', function ( Query_Builder $q ) use ( $user_id ) { $q->select( [ 'e_notes_relevant_replies_ids.id' ] ) ->from( Module::TABLE_NOTES, 'e_notes_relevant_replies_ids' ) ->where_column( 'e_notes_relevant_replies_ids.parent_id', '=', Module::TABLE_NOTES . '.id' ) ->where( 'e_notes_relevant_replies_ids.status', '!=', Note::STATUS_TRASH ); } ) ->where( 'e_notes_relevant_relation_replies.user_id', '=', $user_id ) ->where( 'e_notes_relevant_relation_replies.type', '=', Note::USER_RELATION_MENTION ); }; return $this->where( function ( Query_Builder $q ) use ( $user_id, $replied_to_thread, $mentioned_in_thread, $mentioned_in_replies ) { $q->where( 'author_id', '=', $user_id ) // User created the thread. ->or_where_exists( $replied_to_thread ) ->or_where_exists( $mentioned_in_thread ) ->or_where_exists( $mentioned_in_replies ); } ); } /** * Filter only unread notes. * * @param integer $user_id - User id that the notes are unread by. * * @return Note_Query_Builder */ public function only_unread( $user_id ) { return $this ->with_unread_replies_count( $user_id ) ->with_is_read( $user_id ) ->having_raw( '`unread_replies_count` > 0 OR `is_read` = 0' ); } /** * Filter only threads. * * @return Note_Query_Builder */ public function only_threads() { return $this->where( 'parent_id', '=', 0 ); } /** * Filter only replies. * * @return Note_Query_Builder */ public function only_replies() { return $this->where( 'parent_id', '!=', 0 ); } /** * Filter only trashed notes. * * @return Note_Query_Builder */ public function only_trashed() { return $this->with_trashed() ->where( 'status', '=', Note::STATUS_TRASH ); } /** * Eager load the Note's unread replies count by a user ID. * * @param int $user_id - User ID to check. * * @return Note_Query_Builder */ public function with_unread_replies_count( $user_id ) { $alias = 'unread_replies_count'; if ( $this->is_column_selected( $alias ) ) { return $this; } return $this->add_sub_select( function ( Query_Builder $q ) use ( $user_id ) { $q->select( [ 'e_replies_count.id' ], static::COLUMN_COUNT ) ->from( Module::TABLE_NOTES, 'e_replies_count' ) ->left_join( function ( Join_Clause $j ) use ( $user_id ) { $j->table( Module::TABLE_NOTES_USERS_RELATIONS, 'e_replies_count_user_relations' ) ->on_column( 'e_replies_count_user_relations.note_id', '=', 'e_replies_count.id' ) ->on( 'e_replies_count_user_relations.type', '=', Note::USER_RELATION_READ ) ->on( 'e_replies_count_user_relations.user_id', '=', $user_id ); } ) ->where_column( 'e_replies_count.parent_id', '=', Module::TABLE_NOTES . '.id' ) ->where_null( 'e_replies_count_user_relations.id' ); }, $alias ); } /** * Extends base delete method to allow deleting all the related entities * of the notes, including 'user relations' and 'replies'. * * @param false $include_related_entities * * @return bool|int */ public function delete( $include_related_entities = false ) { if ( ! $include_related_entities ) { return parent::delete(); } // Get all the ids of the notes it wishes to delete. $notes_ids = $this->select( [ 'id' ] ) ->with_trashed() ->get() ->pluck( 'id' ); if ( $notes_ids->is_empty() ) { return 0; } // Get all the replies ids. $replies_ids = Note::query() ->with_trashed() ->select( [ 'id' ] ) ->where_in( 'parent_id', $notes_ids->values() ) ->get() ->pluck( 'id' ); // Merge the thread ids with the replies. $all_relevant_notes_ids = $notes_ids->merge( $replies_ids ); // Delete all the users relations of the notes. ( new Query_Builder() ) ->table( Module::TABLE_NOTES_USERS_RELATIONS ) ->where_in( 'note_id', $all_relevant_notes_ids->values() ) ->delete(); // Delete all the notes. return Note::query() ->with_trashed() ->where_in( 'id', $all_relevant_notes_ids->values() ) ->delete(); } /** * Move notes to trash. * * @return bool|int */ public function trash() { $now = gmdate( 'Y-m-d H:i:s' ); return $this->update( [ 'status' => Note::STATUS_TRASH, 'updated_at' => $now, ] ); } /** * Restore notes from trash. * * @return bool|int */ public function restore() { $now = gmdate( 'Y-m-d H:i:s' ); return $this ->with_trashed() ->where( 'status', '=', Note::STATUS_TRASH ) ->update( [ 'status' => Note::STATUS_PUBLISH, // TODO: It should be the last status 'updated_at' => $now, ] ); } }
| ver. 1.4 |
Github
|
.
| PHP 7.4.3-4ubuntu2.24 | Генерация страницы: 0 |
proxy
|
phpinfo
|
Настройка