8889841cPK [=X X DonationHistoryTab/Tab.phpnu [ donorDashboard->getId(); $repository = new DonationsRepository(); return $this->getData($repository, $donorId); } /** * @since 2.10.2 * * @param DonationsRepository $repository * @param $donorId * * @return WP_REST_Response */ protected function getData(DonationsRepository $repository, $donorId) { // If the provided donor ID is valid, attempt to query data try { $donations = $repository->getDonations($donorId); $count = $repository->getDonationCount($donorId); $revenue = $repository->getRevenue($donorId); $average = $repository->getAverageRevenue($donorId); $currency = [ 'symbol' => give_currency_symbol(give_get_currency(), true), 'position' => give_get_currency_position(), ]; return new WP_REST_Response( [ 'status' => 200, 'response' => 'success', 'body_response' => [ [ 'donations' => $donations, 'count' => $count, 'revenue' => $revenue, 'average' => $average, 'currency' => $currency, ], ], ] ); } catch (\Exception $e) { Log::error( esc_html__('An error occurred while retrieving donation records', 'give'), [ 'source' => 'Donor Dashboard', 'Donor ID' => $donorId, 'Error' => $e->getMessage(), ] ); return new WP_REST_Response( [ 'status' => 400, 'response' => 'database_error', 'body_response' => [ 'message' => esc_html__( 'An error occurred while retrieving your donation records. Contact the site administrator for assistance.', 'give' ), ], ] ); } } } PK [Q{ Contracts/Tab.phpnu [ routes(); foreach ($routeClasses as $routeClass) { if ( ! is_subclass_of($routeClass, RouteAbstract::class)) { throw new \InvalidArgumentException( $routeClass . ' must extend the ' . RouteAbstract::class . ' class' ); } (new $routeClass)->registerRoute(); } } public function registerTab() { give()->donorDashboardTabs->addTab(get_called_class()); } } PK ['~C C Contracts/Route.phpnu [ root}{$this->endpoint()}", [ [ 'methods' => 'POST', 'callback' => [$this, 'handleRequestWithDonorIdCheck'], 'permission_callback' => function () { return DonorDashboardHelpers::isDonorLoggedIn(); }, ], 'args' => $this->args(), ] ); } /** * @since 2.26.0 add try/catch to handleRequest */ public function handleRequestWithDonorIdCheck(WP_REST_Request $request) { // Check that the provided donor ID is valid if (!Give()->donors->get_donor_by('id', give()->donorDashboard->getId())) { Log::error( esc_html__('An error occurred while validating donor ID on request.', 'give'), [ 'source' => 'Donor Dashboard', 'Donor ID' => give()->donorDashboard->getId(), 'Current User ID' => get_current_user_id(), 'Email Access Token' => give()->email_access->token_email, 'Session Email' => give()->session->get('give_email'), 'Session Expiration' => give()->session->get_session_expiration(), 'Error' => __('Donor ID could not be validated for request.', 'give'), ] ); return new WP_REST_Response( [ 'status' => 400, 'response' => 'invalid_donor_id', 'body_response' => [ 'message' => html_entity_decode( esc_html__( 'An error occurred while retrieving your donation records. Contact a site administrator and have them search the logs at Donations > Tools > Logs for a more specific cause of the problem.', 'give' ) ), ], ] ); } try { $response = $this->handleRequest($request); return rest_ensure_response($response ?? []); } catch (Exception $exception) { $error = new WP_Error('error', $exception->getMessage()); return rest_ensure_response($error); } } } PK [V& TabsRegister.phpnu [ tabs; } /** * Checks to see if a tab is registered with the given ID * * @since 2.10.0 * * @param string $id * * @return bool */ public function hasTab($id) { return isset($this->tabs[$id]); } /** * Returns a tab with the given ID * * @since 2.10.0 * * @param string $id * * @return string */ public function getTab($id) { if ( ! $this->hasTab($id)) { throw new MissingTabException($id); } return $this->tabs[$id]; } /** * Returns all of the registered tab ids * * @since 2.10.0 * * @return string[] */ public function getRegisteredIds() { return array_keys($this->tabs); } /** * Add a tab to the list of tabs * * @since 2.10.0 * * @param string $tabClass FQCN of the Tab Class */ public function addTab($tabClass) { if ( ! is_subclass_of($tabClass, Tab::class)) { throw new \InvalidArgumentException('Class must extend the ' . Tab::class . ' class'); } $tabId = $tabClass::id(); if ($this->hasTab($tabId)) { throw new DuplicateTabException(); } $this->tabs[$tabId] = $tabClass; } /** * Helper for adding a bunch of tabs at once * * @since 2.10.0 * * @param string[] $tabClasses */ public function addTabs(array $tabClasses) { foreach ($tabClasses as $tabClass) { $this->addTab($tabClass); } } public function registerTabRoutes() { foreach (give()->donorDashboardTabs->tabs as $tabClass) { $tab = new $tabClass; $tab->registerRoutes(); } } public function enqueueTabAssets() { foreach (give()->donorDashboardTabs->tabs as $tabClass) { (new $tabClass)->enqueueAssets(); } } } PK [5ث0 0 EditProfileTab/AvatarRoute.phpnu [ 400, 'response' => 'missing_files', 'body_response' => [ 'message' => __('No files were included in request for upload.', 'give'), ], ] ); } // Delete existing Donor profile avatar attachment if (give()->donorDashboard->getAvatarId()) { wp_delete_attachment(give()->donorDashboard->getAvatarId(), true); } if ( ! function_exists('wp_handle_upload')) { require_once(ABSPATH . 'wp-admin/includes/file.php'); } foreach ($_FILES as $file) { $upload = wp_handle_upload( $file, [ 'test_form' => false, ] ); if (isset($upload['url'])) { $path = $upload['url']; // Check the type of file. We'll use this as the 'post_mime_type'. $filetype = wp_check_filetype(basename($path), null); // Prepare an array of post data for the attachment. $attachment = [ 'guid' => $path, 'post_mime_type' => $filetype['type'], 'post_title' => preg_replace('/\.[^.]+$/', '', basename($path)), 'post_content' => '', 'post_status' => 'inherit', ]; // Insert the attachment. $attachmentId = wp_insert_attachment($attachment, $path); // Make sure that this file is included, as wp_generate_attachment_metadata() depends on it. require_once(ABSPATH . 'wp-admin/includes/image.php'); // Generate the metadata for the attachment, and update the database record. $attachmentData = wp_generate_attachment_metadata($attachmentId, $path); wp_update_attachment_metadata($attachmentId, $attachmentData); return [ 'id' => $attachmentId, ]; } } return new WP_REST_Response( [ 'status' => 404, 'response' => 'not_found', 'body_response' => [ 'message' => __('No file with an upload URL was found', 'give'), ], ] ); } } PK [+ EditProfileTab/Tab.phpnu [ [ 'type' => 'string', 'required' => true, 'sanitize_callback' => 'sanitize_text_field', ], ]; } /** * @since 2.10.0 * * @param WP_REST_Request $request * * @return array * */ public function handleRequest(WP_REST_Request $request) { return [ 'states' => LocationList::getStates( $request->get_param('countryCode') ), ]; } } PK [ EditProfileTab/ProfileRoute.phpnu [ [ 'type' => 'string', 'required' => true, 'sanitize_callback' => [$this, 'sanitizeData'], ], 'id' => [ 'type' => 'int', 'required' => true, ], ]; } /** * Handles profile update, and returns updated profile array * * @since 2.10.0 * * @param WP_REST_Request $request * * @return array * */ public function handleRequest(WP_REST_Request $request) { return $this->updateProfile($request->get_param('data'), give()->donorDashboard->getId()); } /** * Updates profile model, then gets newly stored profile data to return * * @since 2.10.0 * * @param int $id Profile id to update * * @param object $data Object representing profile data to update * * @return array * */ protected function updateProfile($data, $id) { $profile = new Profile($id); $profile->update($data); return [ 'profile' => $profile->getProfileData(), ]; } /** * Sanitize profile data object * * @since 2.10.0 * * @param \WP_REST_Request $request * @param string $param * * @param string $value JSON encoded string representing profile data * * @return object * */ public function sanitizeData($value, $request, $param) { $sanitizeHelper = '\Give\DonorDashboards\Helpers\SanitizeProfileData'; $values = json_decode($value); return [ 'firstName' => sanitize_text_field($values->firstName), 'lastName' => sanitize_text_field($values->lastName), 'company' => sanitize_text_field($values->company), 'additionalEmails' => SanitizeHelper::sanitizeAdditionalEmails($values->additionalEmails), 'additionalAddresses' => SanitizeHelper::sanitizeAdditionalAddresses($values->additionalAddresses), 'primaryEmail' => sanitize_email($values->primaryEmail), 'primaryAddress' => SanitizeHelper::sanitizeAddress($values->primaryAddress), 'titlePrefix' => sanitize_text_field($values->titlePrefix), 'avatarId' => SanitizeHelper::sanitizeInt($values->avatarId), 'isAnonymous' => intval($values->isAnonymous), ]; } protected function sanitizeValue($value, $config) { if ( ! empty($value) && is_callable($config['sanitizeCallback'])) { return $config['sanitizeCallback']($value); } else { return $config['default']; } } } PK K[DP3$ 3$ Abstract.phpnu [ $this, ); return Tribe__Events__Aggregator__Page::instance()->template( 'tabs/' . $this->get_slug(), $data ); } /** * The constructor for any new Tab on the Aggregator, * If you need an action to be hook to any Tab, use this. */ public function __construct() { } /** * Fetches the link to this tab * * @param array|string $args Query String or Array with the arguments * @param boolean $relative Return a relative URL or absolute * * @return string */ public function get_url( $args = array(), $relative = false ) { $defaults = array( 'tab' => $this->get_slug(), ); // Allow the link to be "changed" on the fly $args = wp_parse_args( $args, $defaults ); // Escape after the filter return Tribe__Events__Aggregator__Page::instance()->get_url( $args, $relative ); } /** * Determines if this Tab is currently displayed * * @return boolean */ public function is_active() { return Tribe__Events__Aggregator__Tabs::instance()->is_active( $this->get_slug() ); } public function handle_submit() { $data = array( 'message' => __( 'There was a problem processing your import. Please try again.', 'the-events-calendar' ), ); if ( ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) && ! $this->is_active() ) { return; } if ( 'POST' !== $_SERVER['REQUEST_METHOD'] ) { return; } if ( empty( $_POST['aggregator'] ) ) { return; } // validate nonce if ( empty( $_POST['tribe_aggregator_nonce'] ) || ! wp_verify_nonce( $_POST['tribe_aggregator_nonce'], 'tribe-aggregator-save-import' ) ) { wp_send_json_error( $data ); } $post_data = $_POST['aggregator']; if ( empty( $post_data['origin'] ) || empty( $post_data[ $post_data['origin'] ] ) ) { wp_send_json_error( $data ); } $data = $post_data[ $post_data['origin'] ]; // If we are dealing with Other URL made if ( 'url' === $post_data['origin'] ) { $new_origin = tribe( 'events-aggregator.settings' )->match_source_origin( $data['source'] ); // If we found a valid new origin we overwrite if ( false !== $new_origin ) { $post_data['origin'] = $new_origin; } } $record = Tribe__Events__Aggregator__Records::instance()->get_by_origin( $post_data['origin'] ); $meta = [ 'import_name' => empty( $post_data['import_name'] ) ? '' : sanitize_text_field( trim( $post_data['import_name'] ) ), 'origin' => $post_data['origin'], 'type' => empty( $data['import_type'] ) ? 'manual' : $data['import_type'], 'frequency' => empty( $data['import_frequency'] ) ? null : $data['import_frequency'], 'file' => empty( $data['file'] ) ? null : $data['file'], 'keywords' => ! isset( $data['keywords'] ) ? null : trim( $data['keywords'] ), 'location' => ! isset( $data['location'] ) ? null : trim( $data['location'] ), 'start' => ! isset( $data['start'] ) ? null : trim( $data['start'] ), 'end' => ! isset( $data['end'] ) ? null : trim( $data['end'] ), 'radius' => empty( $data['radius'] ) ? null : $data['radius'], 'source' => empty( $data['source'] ) ? null : $data['source'], 'source_type' => empty( $data['source_type'] ) ? null : $data['source_type'], 'content_type' => empty( $data['content_type'] ) ? null : $data['content_type'], 'schedule_day' => empty( $data['schedule_day'] ) ? null : $data['schedule_day'], 'schedule_time' => empty( $data['schedule_time'] ) ? null : $data['schedule_time'], ]; // Special source types can override source (Eventbrite current profile URL) if ( ! empty( $meta['source_type'] ) ) { $meta['source'] = $meta['source_type']; } /** * Filters the meta used during submit. * * @since 5.1.0 * * @param array $meta Import meta. */ $meta = apply_filters( 'tribe_aggregator_import_submit_meta', $meta ); // Only apply this verification when dealing with Creating new items if ( ! empty( $post_data['action'] ) && 'new' === $post_data['action'] ) { $hash = array_filter( $meta ); // remove non-needed data from the Hash of the Record unset( $hash['schedule_day'], $hash['schedule_time'] ); ksort( $hash ); $hash = md5( maybe_serialize( $hash ) ); /** @var Tribe__Events__Aggregator__Record__Abstract $match */ $match = tribe( 'events-aggregator.records' )->find_by_data_hash( $meta['source'], $hash ); if ( $match instanceof Tribe__Events__Aggregator__Record__Abstract ) { $url = get_edit_post_link( $match->id ); $anchor = '' . esc_attr__( 'click here to edit it', 'the-events-calendar' ) . ''; $message = sprintf( __( 'A record already exists with these settings, %1$s.', 'the-events-calendar' ), $anchor ); wp_send_json_error( array( 'message' => $message ) ); } } $meta = $this->validate_meta_by_origin( $meta['origin'], $meta ); if ( is_wp_error( $meta ) ) { /** @var WP_Error $validated */ wp_send_json_error( $meta->get_error_message() ); } return array( 'record' => $record, 'post_data' => $post_data, 'meta' => $meta, ); } /** * Validates the meta in relation to the origin. * * @param string $origin * @param array $meta * * @return array|WP_Error The updated/validated meta array or A `WP_Error` if the validation failed. */ protected function validate_meta_by_origin( $origin, $meta ) { $result = $meta; switch ( $origin ) { case 'csv': case 'ics': if ( empty( $meta['file'] ) ) { $result = new WP_Error( 'missing-file', __( 'Please provide the file that you wish to import.', 'the-events-calendar' ) ); } break; case 'eventbrite': if ( empty( $meta['source'] ) || ! preg_match( '/' . Tribe__Events__Aggregator__Record__Eventbrite::get_source_regexp() . '/', $meta['source'] ) ) { $result = new WP_Error( 'not-eventbrite-url', __( 'Please provide a Eventbrite URL when importing from Eventbrite.', 'the-events-calendar' ) ); } break; case 'meetup': if ( empty( $meta['source'] ) || ! preg_match( '/' . Tribe__Events__Aggregator__Record__Meetup::get_source_regexp() . '/', $meta['source'] ) ) { $result = new WP_Error( 'not-meetup-url', __( 'Please provide a Meetup URL when importing from Meetup.', 'the-events-calendar' ) ); } break; case 'url': $now = time(); $range = tribe_get_option( 'tribe_aggregator_default_url_import_range', 30 * DAY_IN_SECONDS ); $start = ! empty( $meta['start'] ) ? $this->to_timestamp( $meta['start'], $now ) : $now; $end = ! empty( $meta['end'] ) ? $this->to_timestamp( $meta['end'], $start + $range ) : $start + $range; /** * Filters the URL import range cap. * * @param int $max_range The duration in seconds of the cap. * @param array $meta The meta for this import request. */ $max_range = apply_filters( 'tribe_aggregator_url_import_range_cap', 3 * 30 * DAY_IN_SECONDS, $meta ); // but soft-cap the range to start + cap at the most $end = min( $end, $start + $max_range ); /** * Filters the URL import range start date after the cap has been applied. * * @param int $start The start date UNIX timestamp. * @param int $end The end date UNIX timestamp. * @param array $meta The meta for this import request. */ $start = apply_filters( 'tribe_aggregator_url_import_range_start', $start, $end, $meta ); /** * Filters the URL import range end date after the cap has been applied. * * @param int $end The end date UNIX timestamp. * @param int $start The start date UNIX timestamp. * @param array $meta The meta for this import request. */ $end = apply_filters( 'tribe_aggregator_url_import_range_end', $end, $start, $meta ); $result['start'] = $start; $result['end'] = $end; break; default: if ( empty( $meta['source'] ) ) { $result = new WP_Error( 'missing-url', __( 'Please provide the URL that you wish to import.', 'the-events-calendar' ) ); } break; } /** * Filters the validation result for custom validations and overrides. * * @since 4.6.24 * * @param array|WP_Error $result The updated/validated meta array or A `WP_Error` if the validation failed. * @param string $origin Origin name. * @param array $meta Import meta. */ $result = apply_filters( 'tribe_aggregator_import_validate_meta_by_origin', $result, $origin, $meta ); return $result; } /** * Casts a string or int to a timestamp. * * @param int|string $time * @param int $default The default time that should be used if the conversion of `$time` fails * * @return int */ protected function to_timestamp( $time, $default = '' ) { $time = Tribe__Date_Utils::is_timestamp( $time ) ? $time : strtotime( Tribe__Date_Utils::maybe_format_from_datepicker( $time ) ); return false !== $time ? $time : $default; } } PK K[h. Edit.phpnu [ is_active() ) { return; } wp_enqueue_media(); } public function is_visible() { return true; } public function get_slug() { return 'edit'; } public function get_label() { return esc_html__( 'Edit Import', 'the-events-calendar' ); } public function handle_submit() { $this->messages = [ 'error', 'success', 'warning', ]; if ( empty( $_POST['aggregator']['action'] ) || 'edit' !== $_POST['aggregator']['action'] ) { return; } $submission = parent::handle_submit(); if ( empty( $submission['record'] ) || empty( $submission['post_data'] ) || empty( $submission['meta'] ) ) { return; } $record = $submission['record']; $post_data = $submission['post_data']; $meta = $submission['meta']; if ( ! empty( $post_data['post_id'] ) ) { $this->finalize_schedule_edit( $record, $post_data, $meta ); return; } $post = $record->create( $meta['type'], [], $meta ); if ( is_wp_error( $post ) ) { return $post; } $result = $record->queue_import(); if ( is_wp_error( $post ) ) { return $post; } return $result; } /** * Finalizes the saving of a scheduled import * * @param Tribe__Events__Aggregator__Record__Abstract $record Record object * @param array $post_data Massaged POSTed data * @param array $meta Meta to be saved to the schedule */ public function finalize_schedule_edit( $record, $post_data, $meta ) { $this->messages = [ 'error' => [], 'success' => [], 'warning' => [], ]; $meta['post_status'] = empty( $post_data['post_status'] ) ? 'draft' : $post_data['post_status']; $meta['category'] = Tribe__Utils__Array::get( $post_data, 'category', null ); $result = $record->save( $post_data['post_id'], [], $meta ); if ( is_wp_error( $result ) ) { $this->messages['error'][] = $result->get_error_message(); ob_start(); ?>
messages['error'] ); ?>
messages['success'][] = esc_html__( 'Scheduled import was successfully updated.' ); ob_start(); ?> messages['success'][] = __( 'Your Scheduled Import has been updated!', 'the-events-calendar' ); tribe_notice( 'tribe-aggregator-schedule-edit-complete', $html, 'type=success' ); return $result; } /** * Handles the previewing of a scheduled import edit */ public function ajax_preview_import() { $result = $this->handle_submit(); if ( is_wp_error( $result ) ) { $result = (object) [ 'message_code' => $result->get_error_code(), 'message' => $result->get_error_message(), ]; wp_send_json_error( $result ); } wp_send_json_success( $result ); } } PK K[TY Y History.phpnu [ is_active() ) { return; } $record_screen = WP_Screen::get( Tribe__Events__Aggregator__Records::$post_type ); $args = [ 'label' => esc_html__( 'Records per page', 'the-events-calendar' ), 'default' => 10, 'option' => 'tribe_records_history_per_page', ]; // We need to Add on both because of a WP Limitation on WP_Screen $record_screen->add_option( 'per_page', $args ); $screen->add_option( 'per_page', $args ); } /** * Allows the saving for our created Page option * * @param mixed $status Which value should be saved, if false will not save * @param string $option Name of the option * @param mixed $value Which value was saved * * @return mixed */ public function filter_save_screen_options( $status, $option, $value ) { if ( 'tribe_records_history_per_page' === $option ) { return $value; } return $status; // or return false; } public function is_visible() { $records = Tribe__Events__Aggregator__Records::instance(); return $records->has_scheduled() || $records->has_history(); } public function get_slug() { return 'history'; } public function get_label() { return esc_html__( 'History', 'the-events-calendar' ); } } PK K[GB Favorite.phpnu [ is_active() ) { return; } $record_screen = WP_Screen::get( Tribe__Events__Aggregator__Records::$post_type ); $args = array( 'label' => esc_html__( 'Records per page', 'the-events-calendar' ), 'default' => 10, 'option' => 'tribe_records_scheduled_per_page', ); $record_screen->add_option( 'per_page', $args ); $screen->add_option( 'per_page', $args ); } /** * Allows the saving for our created Page option * * @param mixed $status Which value should be saved, if false will not save * @param string $option Name of the option * @param mixed $value Which value was saved * * @return mixed */ public function filter_save_screen_options( $status, $option, $value ) { if ( 'tribe_records_scheduled_per_page' === $option ) { return $value; } return $status; // or return false; } public function is_visible() { $records = Tribe__Events__Aggregator__Records::instance(); return $records->has_scheduled(); } public function get_slug() { return 'scheduled'; } public function get_label() { return esc_html__( 'Scheduled Imports', 'the-events-calendar' ); } public function handle_request() { // If we are on AJAX or not on this Tab, We shall not pass if ( ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) && ! $this->is_active() ) { return; } if ( 'POST' === $_SERVER['REQUEST_METHOD'] ) { $this->handle_post(); } elseif ( 'GET' === $_SERVER['REQUEST_METHOD'] ) { $this->handle_get(); } } private function handle_post( $data = null ) { if ( is_null( $data ) ) { if ( ! isset( $_POST['aggregator'] ) ) { return false; } $data = $_POST['aggregator']; } // Ensure it's an Object $data = (object) $data; if ( ! isset( $data->action ) ) { return false; } if ( ! isset( $data->nonce ) || ! wp_verify_nonce( $data->nonce, 'aggregator_' . $this->get_slug() . '_request' ) ) { return false; } if ( empty( $data->records ) ) { if ( empty( $data->ids ) ) { return false; } $data->records = explode( ',', $data->ids ); } // Ensures Records is an Array $data->records = (array) $data->records; switch ( $data->action ) { case 'delete': list( $success, $errors ) = $this->action_delete_record( $data->records ); break; case 'run-import': list( $success, $errors ) = $this->action_run_import( $data->records ); break; } $args = array( 'tab' => $this->get_slug(), 'action' => $data->action, 'ids' => implode( ',', array_keys( $success ) ), ); if ( ! empty( $errors ) ) { $args['errors'] = $data->nonce; // Set the errors set_transient( $this->get_errors_transient_name( $data->nonce ), $errors, 5 * MINUTE_IN_SECONDS ); } $sendback = Tribe__Events__Aggregator__Page::instance()->get_url( $args ); wp_redirect( $sendback ); die; } public function get_errors_transient_name( $nonce ) { return 'tribe-ea-' . $this->get_slug() . '-action-' . $nonce; } private function handle_get() { if ( ! isset( $_GET['action'] ) ) { return false; } switch ( $_GET['action'] ) { case 'run-import'; $action = __( 'queued', 'the-events-calendar' ); break; case 'delete'; $action = __( 'delete', 'the-events-calendar' ); break; case 'reactivate': $action = __( 'reactivated', 'the-events-calendar' ); break; case 'deactivate': $action = __( 'deactivated', 'the-events-calendar' ); break; default: return false; } if ( empty( $_GET['ids'] ) && empty( $_GET['errors'] ) ) { return false; } // If it has a Nonce we do a GET2POST request if ( isset( $_GET['nonce'] ) ) { return $this->handle_post( $_GET ); } $this->action_notice( $action, empty( $_GET['ids'] ) ? array() : $_GET['ids'], isset( $_GET['errors'] ) ? $_GET['errors'] : null ); } /** * Error and success messages for delete * * @param string $action saved, deleted * @param array $statuses Which status occurred * @return string */ private function action_notice( $action, $ids = array(), $error = null ) { if ( $ids && ! is_array( $ids ) ) { $ids = explode( ',', $ids ); } $errors = array(); if ( is_string( $error ) ) { $transient = $this->get_errors_transient_name( $error ); $errors = get_transient( $transient ); // After getting delete delete_transient( $transient ); } $success = count( $ids ); $message = (object) array( 'success' => array(), 'error' => array(), ); if ( ! empty( $errors ) ) { if ( 'run-import' === $_GET['action'] ) { foreach ( $errors as $post_id => $error ) { $message->error[] = $error->get_error_message(); } } else { $message->error[] = sprintf( esc_html__( 'Error: %d scheduled import was not %s.', 'the-events-calendar' ), $action, count( $errors ) ); foreach ( $errors as $post_id => $error ) { $message->error[] = implode( '' . implode( '
', $message->error ) . '
' . implode( "\r\n", $message->success ) . '
', 'type=success' ); } } private function action_delete_record( $records = array() ) { $record_obj = Tribe__Events__Aggregator__Records::instance()->get_post_type(); $records = array_filter( (array) $records, 'is_numeric' ); $success = []; $errors = []; foreach ( $records as $record_id ) { $record = Tribe__Events__Aggregator__Records::instance()->get_by_post_id( $record_id ); if ( tribe_is_error( $record ) ) { $errors[ $record_id ] = $record; continue; } if ( ! current_user_can( $record_obj->cap->delete_post, $record->id ) ) { $errors[ $record->id ] = tribe_error( 'core:aggregator:delete-record-permissions', array( 'record' => $record ) ); continue; } $status = $record->delete( true ); if ( is_wp_error( $status ) ) { $errors[ $record->id ] = $status; continue; } $success[ $record->id ] = true; } return [ $success, $errors ]; } /** * Run Imports for a given set of Records * * @since 4.6.18 * * @param array $records * * @return array */ public function action_run_import( $records = [] ) { $service = tribe( 'events-aggregator.service' ); $records = array_filter( (array) $records, 'is_numeric' ); $success = []; $errors = []; foreach ( $records as $record_id ) { $record = Tribe__Events__Aggregator__Records::instance()->get_by_post_id( $record_id ); if ( tribe_is_error( $record ) ) { $errors[ $record_id ] = $record; continue; } // if there are no remaining imports for today, log that and skip if ( $service->is_over_limit( true ) ) { $errors[ $record->id ] = new WP_Error( 'error:usage-limit-exceeded', $service->get_service_message( 'error:usage-limit-exceeded', (array) tribe( 'events-aggregator.main' )->get_daily_limit() ) ); $record->update_meta( 'last_import_status', 'error:usage-limit-exceeded' ); continue; } $child = $record->create_child_record(); $child->update_meta( 'interactive', true ); $status = $child->queue_import(); if ( is_wp_error( $status ) ) { $errors[ $record->id ] = $status; $record->update_meta( 'last_import_status', 'error:import-failed' ); continue; } $child->finalize(); $post = $child->process_posts( [], true ); if ( is_wp_error( $post ) ) { $errors[ $record->id ] = $post; $record->update_meta( 'last_import_status', 'error:import-failed' ); } else { $record->update_meta( 'last_import_status', 'success:queued' ); $child->update_meta( 'import_id', $status->data->import_id ); $success[ $record->id ] = $record; } } return [ $success, $errors ]; } /** * Renders the "Missing Aggregator License" notice * * @return string */ public function maybe_display_aggregator_missing_license_key_message() { if ( tribe( 'events-aggregator.main' )->is_service_active() ) { return ''; } ob_start(); ?> k[ [ New.phpnu [ is_active() ) { return; } $license_info = get_option( 'external_updates-event-aggregator' ); if ( isset( $license_info->update->api_expired ) && $license_info->update->api_expired ) { tribe_notice( 'tribe-expired-aggregator-license', array( $this, 'render_notice_expired_aggregator_license' ), 'type=warning' ); } } public function enqueue_media() { if ( ! $this->is_active() ) { return; } wp_enqueue_media(); } public function is_visible() { return true; } public function get_slug() { return 'new'; } public function get_label() { return esc_html__( 'New Import', 'the-events-calendar' ); } public function handle_submit() { if ( empty( $_POST['aggregator']['action'] ) || 'new' !== $_POST['aggregator']['action'] ) { return; } $submission = parent::handle_submit(); if ( empty( $submission['record'] ) || empty( $submission['post_data'] ) || empty( $submission['meta'] ) ) { return; } /** @var Tribe__Events__Aggregator__Record__Abstract $record */ $record = $submission['record']; $post_data = $submission['post_data']; $meta = $submission['meta']; // mark the record creation as a preview record $meta['preview'] = true; if ( ! empty( $post_data['import_id'] ) ) { $this->handle_import_finalize( $post_data ); return; } // Prevents Accidents if ( 'manual' === $meta['type'] ) { $meta['frequency'] = null; } $post = $record->create( $meta['type'], array(), $meta ); if ( is_wp_error( $post ) ) { return $post; } $result = $record->queue_import(); return $result; } public function handle_import_finalize( $data ) { $this->messages = array( 'error' => array(), 'success' => array(), 'warning' => array(), ); $record = Tribe__Events__Aggregator__Records::instance()->get_by_import_id( $data['import_id'] ); if ( tribe_is_error( $record ) ) { $this->messages['error'][] = $record->get_error_message(); return $this->messages; } // Make sure we have a post status set no matter what if ( empty( $data['post_status'] ) ) { $data['post_status'] = tribe( 'events-aggregator.settings' )->default_post_status( $data['origin'] ); } // If the submitted category is null, that means the user intended to de-select the default // category if there is one, so setting it to null is ok here $record->update_meta( 'category', empty( $data['category'] ) ? null : $data['category'] ); $record->update_meta( 'post_status', $data['post_status'] ); $record->update_meta( 'ids_to_import', empty( $data['selected_rows'] ) ? 'all' : json_decode( stripslashes( $data['selected_rows'] ) ) ); /** * Allow hooking into the import record saving process. * * @since 5.1.0 * * @param Tribe__Events__Aggregator__Record__Abstract $record Import record. * @param array $data List of import options. */ do_action( 'tribe_events_aggregator_tabs_new_handle_import_finalize', $record, $data ); // if we get here, we're good! Set the status to pending $record->set_status_as_pending(); $record->finalize(); if ( 'schedule' === $record->meta['type'] ) { $this->messages['success'][] = __( '1 import was scheduled.', 'the-events-calendar' ); $create_schedule_result = $record->create_schedule_record(); if ( is_wp_error( $create_schedule_result ) ) { $this->messages[ 'error' ][] = $create_schedule_result->get_error_message(); tribe_notice( 'tribe-aggregator-import-failed', array( $this, 'render_notice_import_failed' ), 'type=error' ); tribe( 'logger' )->log_debug( 'There was an error while creating the schedule record.', 'EA New' ); $record->set_status_as_failed( $create_schedule_result ); return $create_schedule_result; } } $record->update_meta( 'interactive', true ); if ( 'csv' === $data['origin'] ) { // here generate a global_id for the data $result = $record->process_posts( $data ); } else { // let the record fetch the data and start immediately if possible $result = $record->process_posts( array(), true ); } $result->record = $record; $this->messages = $this->get_result_messages( $result ); if ( empty( $this->messages['error'] ) || ! empty( $this->messages['success'] ) || ! empty( $this->messages['warning'] ) ) { tribe_notice( 'tribe-aggregator-import-complete', array( $this, 'render_notice_import_complete' ), 'type=success' ); } } /** * Parses the queue for errors and informations. * * @param Tribe__Events__Aggregator__Record__Queue_Interface|WP_Error|Tribe__Events__Aggregator__Record__Activity $queue * * @return array */ public function get_result_messages( $queue ) { $messages = array(); if ( is_wp_error( $queue ) ) { $messages[ 'error' ][] = $queue->get_error_message(); tribe_notice( 'tribe-aggregator-import-failed', array( $this, 'render_notice_import_failed' ), 'type=error' ); return $messages; } if ( $queue instanceof Tribe__Events__Aggregator__Record__Queue_Interface && $queue->has_errors() ) { /** @var Tribe__Events__Aggregator__Record__Queue_Interface $queue */ $messages['error'][] = $queue->get_error_message(); tribe_notice( 'tribe-aggregator-import-failed', array( $this, 'render_notice_import_failed' ), 'type=error' ); return $messages; } $is_queued = $queue->count(); $content_post_type = empty( $queue->record->meta['content_type'] ) ? Tribe__Events__Main::POSTTYPE : $queue->record->meta['content_type']; $content_type = tribe_get_event_label_singular_lowercase(); $content_type_plural = tribe_get_event_label_plural_lowercase(); if ( 'csv' === $queue->record->meta['origin'] && 'tribe_events' !== $queue->record->meta['content_type'] ) { $content_type_object = get_post_type_object( $queue->record->meta['content_type'] ); $content_type = empty( $content_type_object->labels->singular_name_lowercase ) ? $content_type_object->labels->singular_name : $content_type_object->labels->singular_name_lowercase; $content_type_plural = empty( $content_type_object->labels->plural_name_lowercase ) ? $content_type_object->labels->name : $content_type_object->labels->plural_name_lowercase; $content_post_type = $content_type_object->name; } if ( ! $is_queued ) { $item_created = $queue->activity->get( $content_post_type, 'created' ); if ( ! empty( $item_created ) ) { $content_label = 1 === $queue->activity->count( $content_post_type, 'created' ) ? $content_type : $content_type_plural; $messages['success'][] = sprintf( // add created event count _n( '%1$d new %2$s was imported.', '%1$d new %2$s were imported.', $queue->activity->count( $content_post_type, 'created' ), 'the-events-calendar' ), $queue->activity->count( $content_post_type, 'created' ), $content_label ); } $item_updated = $queue->activity->get( $content_post_type, 'updated' ); if ( ! empty( $item_updated ) ) { $content_label = 1 === $queue->activity->count( $content_post_type, 'updated' ) ? $content_type : $content_type_plural; // @todo [BTRIA-589]: Include a part of sentence like: ", including %1$d %2$signored event%3$s.", , . $messages['success'][] = sprintf( // add updated event count _n( '%1$d existing %2$s was updated.', '%1$d existing %2$s were updated.', $queue->activity->count( $content_post_type, 'updated' ), 'the-events-calendar' ), $queue->activity->count( $content_post_type, 'updated' ), $content_label ); } $item_skipped = $queue->activity->get( $content_post_type, 'skipped' ); if ( ! empty( $item_skipped ) ) { $content_label = 1 === $queue->activity->count( $content_post_type, 'skipped' ) ? $content_type : $content_type_plural; $messages['success'][] = sprintf( // add skipped event count _n( '%1$d already-imported %2$s was skipped.', '%1$d already-imported %2$s were skipped.', $queue->activity->count( $content_post_type, 'skipped' ), 'the-events-calendar' ), $queue->activity->count( $content_post_type, 'skipped' ), $content_label ); } $images_created = $queue->activity->get( 'images', 'created' ); if ( ! empty( $images_created ) ) { $messages['success'][] = sprintf( // add image import count _n( '%1$d new image was imported.', '%1$d new images were imported.', $queue->activity->count( 'images', 'created' ), 'the-events-calendar' ), $queue->activity->count( 'images', 'created' ) ); } $images_scheduled = $queue->activity->get( 'images', 'scheduled' ); if ( ! empty( $images_scheduled ) ) { $messages['success'][] = sprintf( // translators: %1$d is replaced with a number of scheduled images. _n( '%1$d new image was scheduled for import.', '%1$d new images were scheduled for import.', $queue->activity->count( 'images', 'scheduled' ), 'the-events-calendar' ), $queue->activity->count( 'images', 'scheduled' ) ); } if ( $queue && ! $messages ) { $messages['success'][] = sprintf( __( 'No %1$s were imported or updated.', 'the-events-calendar' ), $content_type_plural ); } if ( ! empty( $messages['success'] ) && ! empty( $content_type_object->show_ui ) ) { // append a URL to view all records for the given post type $url = admin_url( 'edit.php?post_type=' . $content_post_type ); $link_text = sprintf( __( 'View all %s', 'the-events-calendar' ), $content_type_plural ); $messages['success'][ count( $messages['success'] ) - 1 ] .= ' ' . esc_html( $link_text ) . ''; } // if not CSV, pull counts for venues and organizers that were auto-created if ( 'csv' !== $queue->record->meta['origin'] ) { $venue_created = $queue->activity->get( 'venue', 'created' ); if ( ! empty( $venue_created ) ) { $messages['success'][] = 'render( 'tribe-expired-aggregator-license', $html ); } /** * Renders any of the "import complete" messages */ public function render_notice_import_complete() { if ( empty( $this->messages['success'] ) ) { return null; } $html = '
' . implode( ' ', $this->messages[ 'success' ] ) . '
'; return Tribe__Admin__Notices::instance()->render( 'tribe-aggregator-import-complete', $html ); } /** * Renders failed import messages */ public function render_notice_import_failed() { if ( empty( $this->messages['error'] ) ) { return null; } $html = '' . implode( ' ', $this->messages['error'] ) . '
'; return Tribe__Admin__Notices::instance()->render( 'tribe-aggregator-import-failed', $html ); } /** * @deprecated 4.6.23 */ public function handle_facebook_credentials() { _deprecated_function( __FUNCTION__, '4.6.23', 'Importing from Facebook is no longer supported in Event Aggregator.' ); /** * Verify that we are dealing with a FB token Request */ if ( ! isset( $_GET['ea-fb-token'] ) ) { return false; } /** * @todo include a way to handle errors on the Send back URL */ $api = tribe( 'events-aggregator.service' )->api(); $response = tribe( 'events-aggregator.service' )->get_facebook_token(); $type = $_GET['ea-fb-token']; if ( is_wp_error( $response ) ) { return false; } if ( empty( $response->data ) ) { return false; } if ( empty( $response->data->expires ) || empty( $response->data->token ) || empty( $response->data->scopes ) ) { return false; } $url_map = array( 'new' => Tribe__Events__Aggregator__Page::instance()->get_url( array( 'tab' => $this->get_slug(), 'ea-auth' => 'facebook' ) ), 'settings' => tribe( Settings::class )->get_url( array( 'tab' => 'addons', 'ea-auth' => 'facebook' ) ), ); if ( ! isset( $url_map[ $type ] ) ) { return false; } // Calculate when will this Token Expire $expires = absint( trim( preg_replace( '/[^0-9]/', '', $response->data->expires ) ) ); $expires += time(); // Save the Options tribe_update_option( 'fb_token', trim( preg_replace( '/[^a-zA-Z0-9]/', '', $response->data->token ) ) ); tribe_update_option( 'fb_token_expires', $expires ); tribe_update_option( 'fb_token_scopes', trim( preg_replace( '/[^a-zA-Z0-9\,_-]/', '', $response->data->scopes ) ) ); // Send it back to the Given Url wp_redirect( $url_map[ $type ] ); exit; } } PK [Oޭ Tab.phpnu W+A registerAssets(); } public function name(): string { return Str::studly(class_basename(get_called_class())); } public function component(): string { return Str::snake(class_basename(get_called_class()), '-'); } public function beforeRenderingErrorPage(Flare $flare, Throwable $throwable) { $this->flare = $flare; $this->throwable = $throwable; } public function script(string $name, string $path) { $this->scripts[$name] = $path; return $this; } public function style(string $name, string $path) { $this->styles[$name] = $path; return $this; } abstract protected function registerAssets(); public function meta(): array { return []; } public function jsonSerialize() { return [ 'title' => $this->name(), 'component' => $this->component(), 'props' => [ 'meta' => $this->meta(), ], ]; } } PK [=X X DonationHistoryTab/Tab.phpnu [ PK [B % DonationHistoryTab/DonationsRoute.phpnu [ PK [Q{ Contracts/Tab.phpnu [ PK ['~C C % Contracts/Route.phpnu [ PK [V& " TabsRegister.phpnu [ PK [5ث0 0 , EditProfileTab/AvatarRoute.phpnu [ PK [+ Q9 EditProfileTab/Tab.phpnu [ PK [\z @; EditProfileTab/LocationRoute.phpnu [ PK [