--- a/timetics/core/appointments/api-appointment-taxonomy.php
+++ b/timetics/core/appointments/api-appointment-taxonomy.php
@@ -384,6 +384,7 @@
'type' => $appointment->get_type(),
'locations' => $appointment->get_locations(),
'price' => $appointment->get_price(),
+ 'visibility' => $appointment->get_visibility(),
];
return $data;
--- a/timetics/core/base.php
+++ b/timetics/core/base.php
@@ -10,6 +10,7 @@
namespace TimeticsCore;
use Hooks;
+use Timetics;
use TimeticsCoreAppointmentsApiAppointmentTaxonomy;
use TimeticsCoreAppointmentsAppointment;
use TimeticsCoreBookingsBooking;
@@ -17,6 +18,7 @@
use TimeticsCoreServicesService;
use TimeticsCoreStaffStaff;
use TimeticsCoreStaffsStaff as StaffsStaff;
+use TimeticsCoreIntegrationsGoogleServiceGoogle_Calendar_Sync;
use TimeticsUtilsSingleton;
/**
@@ -54,6 +56,7 @@
AppointmentsHooks::instance()->init();
Api_Faker::instance();
ApiAppointmentTaxonomy::instance();
+ Google_Calendar_Sync::instance();
}
}
--- a/timetics/core/bookings/api-booking.php
+++ b/timetics/core/bookings/api-booking.php
@@ -95,16 +95,12 @@
[
'methods' => WP_REST_Server::READABLE,
'callback' => [$this, 'get_item'],
- 'permission_callback' => function () {
- return true;
- },
+ 'permission_callback' => [$this, 'get_item_permission_callback'],
],
[
'methods' => WP_REST_Server::EDITABLE,
'callback' => [$this, 'update_item'],
- 'permission_callback' => function () {
- return true;
- },
+ 'permission_callback' => [$this, 'update_item_permission_callback'],
],
[
'methods' => WP_REST_Server::DELETABLE,
@@ -1237,4 +1233,30 @@
return 0;
}
+
+ /**
+ * Update item permission callback
+ * @param WP_Rest_Request $request
+ * @return bool
+ */
+ public function update_item_permission_callback($request){
+ $nonce = $request->get_header('X-WP-Nonce');
+ if (wp_verify_nonce($nonce, 'wp_rest')) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Get item permission callback
+ * @param WP_Rest_Request $request
+ * @return bool
+ */
+ public function get_item_permission_callback($request){
+ $nonce = $request->get_header('X-WP-Nonce');
+ if (wp_verify_nonce($nonce, 'wp_rest')) {
+ return true;
+ }
+ return false;
+ }
}
--- a/timetics/core/bookings/booking.php
+++ b/timetics/core/bookings/booking.php
@@ -995,4 +995,67 @@
];
}
+ /**
+ * Get Google Calendar Event ID for this booking
+ *
+ * @return string
+ */
+ public function get_google_event_id() {
+ return $this->get_metadata( 'google_event_id' );
+ }
+
+ /**
+ * Set Google Calendar Event ID for this booking
+ *
+ * @param string $event_id
+ * @return bool
+ */
+ public function set_google_event_id( $event_id ) {
+ return $this->save_metadata( 'google_event_id', $event_id );
+ }
+
+ public function set_sync_status( $status ) {
+ return $this->save_metadata( 'google_calendar_sync_status', $status );
+ }
+
+ public function get_sync_status() {
+ return $this->get_metadata( 'google_calendar_sync_status' );
+ }
+ /**
+ * Get all Google Event IDs for all bookings
+ *
+ * @return array
+ */
+ public function get_all_google_event_ids() {
+ $meta_key = $this->meta_prefix . 'google_event_id';
+
+ $posts = get_posts(
+ array(
+ 'post_type' => 'any',
+ 'posts_per_page' => -1,
+ 'meta_query' => array(
+ array(
+ 'key' => $meta_key,
+ 'value' => '',
+ 'compare' => '!=',
+ ),
+ ),
+ 'fields' => 'ids',
+ )
+ );
+
+ if ( empty( $posts ) ) {
+ return array();
+ }
+
+ $event_ids = array();
+ foreach ( $posts as $post_id ) {
+ $event_id = get_post_meta( $post_id, $meta_key, true );
+ if ( ! empty( $event_id ) ) {
+ $event_ids[] = $event_id;
+ }
+ }
+
+ return $event_ids;
+ }
}
--- a/timetics/core/frontend/shortcode.php
+++ b/timetics/core/frontend/shortcode.php
@@ -46,7 +46,7 @@
*/
public function booking_form( $attribute ) {
wp_enqueue_style( 'timetics-vendor' );
- wp_enqueue_style( 'timetics-frontend' );
+ wp_enqueue_style( 'timetics-frontend' );
wp_enqueue_script( 'timetics-flatpickr-scripts' );
wp_enqueue_script( 'timetics-frontend-scripts' );
wp_enqueue_script( 'calendar-locale' );
@@ -57,6 +57,13 @@
];
$controls = json_encode( $data_controls );
+ $visibility = get_post_meta( $id, '_tt_apointment_visibility', true );
+ $is_visible = 'enabled' === $visibility;
+
+ if ( ! $is_visible && ! current_user_can( 'manage_options' ) ) {
+ return '<div class="timetics-shortcode-wrapper"><p>' . esc_html__( 'This booking form is not available.', 'timetics' ) . '</p></div>';
+ }
+
ob_start();
?>
<div class="timetics-shortcode-wrapper">
@@ -73,7 +80,7 @@
*/
public function user_dashboard( $attribute ) {
wp_enqueue_style( 'timetics-vendor' );
- wp_enqueue_style( 'timetics-frontend' );
+ wp_enqueue_style( 'timetics-frontend' );
wp_enqueue_script( 'timetics-frontend-scripts' );
$id = get_current_user_id();
@@ -106,7 +113,7 @@
public function eventin_seat_plan() {
wp_enqueue_style( 'timetics-vendor' );
- wp_enqueue_style( 'timetics-frontend' );
+ wp_enqueue_style( 'timetics-frontend' );
wp_enqueue_script( 'timetics-flatpickr-scripts' );
wp_enqueue_script( 'timetics-frontend-scripts' );
}
@@ -118,7 +125,7 @@
*/
public function meeting_list( $attribute ) {
wp_enqueue_style( 'timetics-vendor' );
- wp_enqueue_style( 'timetics-frontend' );
+ wp_enqueue_style( 'timetics-frontend' );
wp_enqueue_script( 'timetics-flatpickr-scripts' );
wp_enqueue_script( 'timetics-frontend-scripts' );
wp_enqueue_script( 'calendar-locale' );
@@ -151,7 +158,7 @@
*/
public function category_meetings( $attribute ) {
wp_enqueue_style( 'timetics-vendor' );
- wp_enqueue_style( 'timetics-frontend' );
+ wp_enqueue_style( 'timetics-frontend' );
wp_enqueue_script( 'timetics-flatpickr-scripts' );
wp_enqueue_script( 'timetics-frontend-scripts' );
wp_enqueue_script( 'calendar-locale' );
--- a/timetics/core/frontend/templates/meeting-list.php
+++ b/timetics/core/frontend/templates/meeting-list.php
@@ -3,9 +3,15 @@
use TimeticsCoreAppointmentsAppointment as Appointment;
use TimeticsCoreStaffsStaff;
-$meetings = Appointment::all([
+$args = [
'posts_per_page' => $limit
-]);
+];
+
+if ( ! current_user_can( 'manage_options' ) ) {
+ $args['visibility'] = 'enabled';
+}
+
+$meetings = Appointment::all($args);
$staffs = Staff::all();
$terms = get_terms( [
--- a/timetics/core/integrations/google/client.php
+++ b/timetics/core/integrations/google/client.php
@@ -89,14 +89,14 @@
*/
public function get_auth_url() {
$auth_url = add_query_arg(
- [
+ array(
'client_id' => $this->client_id,
'scope' => urlencode_deep( $this->auth_scope ),
'redirect_uri' => $this->redirect_uri,
'response_type' => 'code',
'access_type' => 'offline',
- ], self::TIMETICS_AUTH_URL
+ ), self::TIMETICS_AUTH_URL
);
return $auth_url;
@@ -107,11 +107,11 @@
*
* @return void
*/
- public function set_auth_config( $args = [] ) {
- $defaults = [
+ public function set_auth_config( $args = array() ) {
+ $defaults = array(
'client_id' => '',
'client_secrete' => '',
- ];
+ );
$args = wp_parse_args( $args, $defaults );
@@ -151,15 +151,15 @@
throw new InvalidArgumentException( 'Invalid code' );
}
- $args = [
+ $args = array(
'client_id' => $this->client_id,
'client_secret' => $this->client_secrete,
'code' => $code,
'redirect_uri' => $this->redirect_uri,
'grant_type' => 'authorization_code',
- ];
+ );
- $response = wp_remote_post( self::TIMETICS_TOKEN_URI, [ 'body' => $args ] );
+ $response = wp_remote_post( self::TIMETICS_TOKEN_URI, array( 'body' => $args ) );
$status_code = wp_remote_retrieve_response_code( $response );
@@ -178,15 +178,15 @@
* @return void
*/
public function fetch_access_token_with_refresh_token( $refresh_token ) {
- $args = [
+ $args = array(
'client_id' => $this->client_id,
'client_secret' => $this->client_secrete,
'refresh_token' => $refresh_token,
'redirect_uri' => $this->redirect_uri,
'grant_type' => 'refresh_token',
- ];
+ );
- $response = wp_remote_post( self::TIMETICS_TOKEN_URI, [ 'body' => $args ] );
+ $response = wp_remote_post( self::TIMETICS_TOKEN_URI, array( 'body' => $args ) );
$status_code = wp_remote_retrieve_response_code( $response );
@@ -208,16 +208,16 @@
*/
public function revoke( $token ) {
$response = wp_remote_post(
- self::TIMETICS_REVOKE_URI, [
- 'headers' => [
+ self::TIMETICS_REVOKE_URI, array(
+ 'headers' => array(
'content-type' => 'application/x-www-form-urlencoded',
- ],
+ ),
'body' => build_query(
- [
+ array(
'token' => $token,
- ]
+ )
),
- ]
+ )
);
$status_code = wp_remote_retrieve_response_code( $response );
--- a/timetics/core/integrations/google/service/calendar.php
+++ b/timetics/core/integrations/google/service/calendar.php
@@ -68,12 +68,13 @@
if ( empty( $event['start'] ) ) {
continue;
}
- // error_log(print_r($event['start'], true));
+
$start = ! empty($event['start']['dateTime']) ? $event['start']['dateTime'] : $event['start']['date'];
$end = ! empty($event['end']['dateTime']) ? $event['end']['dateTime'] : $event['end']['date'];
$filtered_events[] = [
+ 'id' => $event['id'] ?? '',
'start_date' => date('Y-m-d', strtotime($start)),
'start_time' => date('H:i:s', strtotime($start)),
'end_date' => date('Y-m-d', strtotime($end)),
@@ -86,6 +87,37 @@
return $filtered_events;
}
+ /**
+ * Get event by ID
+ *
+ * @param string $event_id
+ *
+ * @return JSON | WP_Error
+ */
+ public function get_event( $event_id , $user_id = null ) {
+ if ( ! $user_id ) {
+ $user_id = get_current_user_id();
+ }
+
+ $access_token = timetics_get_google_access_token( $user_id );
+
+ $data = [
+ 'headers' => [
+ 'Authorization' => 'Bearer ' . $access_token,
+ ],
+ ];
+
+ $response = wp_remote_get(self::TIMETICS_CALENDAR_EVENT . $event_id, $data);
+
+ if ( is_wp_error( $response ) ) {
+ return ['error' => $response->get_error_message()];
+ }
+
+ $body = wp_remote_retrieve_body( $response );
+ $event = json_decode($body, true);
+
+ return $event;
+ }
/**
* Create event
--- a/timetics/core/integrations/google/service/google-calendar-sync.php
+++ b/timetics/core/integrations/google/service/google-calendar-sync.php
@@ -0,0 +1,215 @@
+<?php
+/**
+ * Google Calendar Sync Class
+ *
+ * Handles two-way synchronization between Google Calendar and Timetics appointments.
+ *
+ * @package Timetics
+ */
+
+namespace TimeticsCoreIntegrationsGoogleService;
+
+use TimeticsCoreAppointmentsApi_Appointment;
+use TimeticsCoreBookingsBooking;
+use TimeticsCoreCustomersCustomer;
+use TimeticsCoreAppointmentsAppointment;
+use WP_Error;
+use TimeticsUtilsSingleton;
+
+/**
+ * Class Google_Calendar_Sync
+ */
+class Google_Calendar_Sync {
+ use Singleton;
+
+ /**
+ * Google Calendar service instance
+ *
+ * @var Calendar
+ */
+ private $calendar;
+
+ /**
+ * Appointment API instance
+ *
+ * @var Api_Appointment
+ */
+ private $appointment_api;
+
+ /**
+ * Meta key for storing Google Event ID
+ */
+ const EVENT_ID_META_KEY = 'tt_google_calendar_event_id';
+
+ /**
+ * Meta key for storing sync status
+ */
+ const SYNC_STATUS_META_KEY = 'tt_google_calendar_sync_status';
+
+ /**
+ * Meta key for storing ETag
+ */
+ const ETAG_META_KEY = 'tt_google_calendar_etag';
+
+ /**
+ * Constructor
+ */
+ public function __construct() {
+ try {
+ $this->calendar = new Calendar();
+ $this->appointment_api = new Api_Appointment();
+
+ // Add hooks
+ add_action( 'timetics_after_booking_schedule', array( $this, 'sync_booking_to_google_calendar' ), 10, 4 );
+ add_filter( 'timetics/admin/booking/get_items', array( $this, 'get_events_from_google' ) );
+ } catch ( Throwable $e ) {
+ error_log( $e->getMessage() );
+ }
+ }
+
+ /**
+ * Get all Google Event IDs that were created by Timetics
+ *
+ * @return array
+ */
+ private function get_timetics_google_event_ids() {
+ $booking = new Booking();
+ return $booking->get_all_google_event_ids();
+ }
+
+ /**
+ * Sync booking to Google Calendar
+ *
+ * @param int $booking_id Booking ID
+ * @param int $customer_id Customer ID
+ * @param int $meeting_id Meeting ID
+ * @param array $data Booking data
+ *
+ * @return void|WP_Error
+ */
+ public function sync_booking_to_google_calendar( $booking_id, $customer_id, $meeting_id, $data ) {
+ try {
+ if ( ! is_numeric( $booking_id ) || ! is_numeric( $customer_id ) || ! is_numeric( $meeting_id ) ) {
+ return new WP_Error( 'invalid_parameters', 'Invalid parameters provided for Google Calendar sync.' );
+ }
+
+ $booking = new Booking( $booking_id );
+ $meeting = new Appointment( $meeting_id );
+ $customer = new Customer( $customer_id );
+
+ // Get the current user's access token
+ $user_id = get_current_user_id();
+ $access_token = timetics_get_google_access_token( $user_id );
+
+ if ( empty( $access_token ) ) {
+ return new WP_Error( 'no_access_token', 'No Google Calendar access token found. Please reconnect your Google account.' );
+ }
+
+ // Prepare event data
+ $event_data = array(
+ 'access_token' => sanitize_text_field( $access_token ),
+ 'summary' => sanitize_text_field( $meeting->get_name() ),
+ 'description' => sanitize_text_field( $meeting->get_description() ),
+ 'start' => array(
+ 'dateTime' => $booking->get_start_date(),
+ 'timeZone' => wp_timezone_string(),
+ ),
+ 'end' => array(
+ 'dateTime' => $booking->get_end_date(),
+ 'timeZone' => wp_timezone_string(),
+ ),
+ 'attendees' => array(
+ array( 'email' => $customer->get_email() ),
+ ),
+ 'reminders' => array(
+ 'useDefault' => true,
+ ),
+ 'guestsCanInviteOthers' => false,
+ 'guestsCanModify' => false,
+ 'guestsCanSeeOtherGuests' => false,
+ 'timezone' => wp_timezone_string(),
+ );
+
+ // Check if this booking already has a Google Event ID
+ $event_id = $booking->get_google_event_id();
+
+ if ( $event_id ) {
+ // Update existing event
+ $result = $this->calendar->update_event( $event_id, $event_data );
+ } else {
+ // Create new event
+ $result = $this->calendar->create_event( $event_data );
+
+ // Save the event ID for future updates
+ if ( ! empty( $result['id'] ) ) {
+ $booking->set_google_event_id( $result['id'] );
+ }
+ }
+
+ if ( is_wp_error( $result ) ) {
+ $booking->set_sync_status( 'error' );
+ return $result;
+ }
+
+ $booking->set_sync_status( 'synced' );
+ } catch ( Exception $e ) {
+ return new WP_Error( 'google_calendar_sync_error', $e->getMessage() );
+ }
+ }
+
+ /**
+ * Get events from Google Calendar
+ * Only returns events that were not created by Timetics
+ *
+ * @param array $bookings Existing bookings array
+ *
+ * @return array Modified bookings array with Google Calendar events
+ */
+ public function get_events_from_google( $bookings ) {
+ try {
+ // Get Google Calendar events
+ $events = $this->calendar->get_events( get_current_user_id() );
+
+ if ( is_wp_error( $events ) || empty( $events ) ) {
+ return $bookings;
+ }
+
+ // Get all Timetics-created Google Event IDs
+ $timetics_event_ids = $this->get_timetics_google_event_ids();
+
+ $google_events = array();
+
+ foreach ( $events as $event ) {
+ // Skip events that were created by Timetics
+ if ( in_array( $event['id'] ?? null, $timetics_event_ids, true ) ) {
+ continue;
+ }
+
+ // mapping google events data to timetics booking format
+ $google_events[] = array(
+ 'id' => $event['id'] ?? '',
+ 'order_total' => '',
+ 'title' => $event['summary'] ?? '',
+ 'description' => $event['description'] ?? '',
+ 'date' => $event['start_date'] ?? '',
+ 'start_date' => $event['start_date'] ?? '',
+ 'end_date' => $event['end_date'] ?? '',
+ 'start_time' => $event['start_time'] ?? '',
+ 'end_time' => $event['end_time'] ?? '',
+ 'source' => 'google',
+ 'status' => 'approved',
+ 'random_id' => 'I' . $event['id'] ?? '',
+ 'appointment' => array(
+ 'id' => $event['id'] ?? '',
+ 'name' => $event['summary'] ?? '',
+ ),
+ );
+ }
+
+ // Merge with existing bookings
+ return array_merge( $bookings, $google_events );
+ } catch ( Throwable $e ) {
+ return $bookings;
+ }
+ }
+}
--- a/timetics/timetics.php
+++ b/timetics/timetics.php
@@ -4,7 +4,7 @@
* Plugin Name: Timetics
* Plugin URI: https://arraytics.com/timetics/
* Description: Schedule, Appointment and Seat Booking plugin.
- * Version: 1.0.36
+ * Version: 1.0.37
* Requires at least: 5.2
* Requires PHP: 7.3
* Author: Arraytics
@@ -56,7 +56,7 @@
* @return string
*/
public static function get_version() {
- return '1.0.36';
+ return '1.0.37';
}
/**
--- a/timetics/vendor/autoload.php
+++ b/timetics/vendor/autoload.php
@@ -3,10 +3,20 @@
// autoload.php @generated by Composer
if (PHP_VERSION_ID < 50600) {
- echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
- exit(1);
+ if (!headers_sent()) {
+ header('HTTP/1.1 500 Internal Server Error');
+ }
+ $err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+ if (!ini_get('display_errors')) {
+ if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
+ fwrite(STDERR, $err);
+ } elseif (!headers_sent()) {
+ echo $err;
+ }
+ }
+ throw new RuntimeException($err);
}
require_once __DIR__ . '/composer/autoload_real.php';
-return ComposerAutoloaderInit05cd069eafe0df94d6f2b539707d0acb::getLoader();
+return ComposerAutoloaderInitd02707597fbf5927c7666b74bdb40ea9::getLoader();
--- a/timetics/vendor/composer/ClassLoader.php
+++ b/timetics/vendor/composer/ClassLoader.php
@@ -42,35 +42,37 @@
*/
class ClassLoader
{
- /** @var ?string */
+ /** @var Closure(string):void */
+ private static $includeFile;
+
+ /** @var string|null */
private $vendorDir;
// PSR-4
/**
- * @var array[]
- * @psalm-var array<string, array<string, int>>
+ * @var array<string, array<string, int>>
*/
private $prefixLengthsPsr4 = array();
/**
- * @var array[]
- * @psalm-var array<string, array<int, string>>
+ * @var array<string, list<string>>
*/
private $prefixDirsPsr4 = array();
/**
- * @var array[]
- * @psalm-var array<string, string>
+ * @var list<string>
*/
private $fallbackDirsPsr4 = array();
// PSR-0
/**
- * @var array[]
- * @psalm-var array<string, array<string, string[]>>
+ * List of PSR-0 prefixes
+ *
+ * Structured as array('F (first letter)' => array('FooBar (full prefix)' => array('path', 'path2')))
+ *
+ * @var array<string, array<string, list<string>>>
*/
private $prefixesPsr0 = array();
/**
- * @var array[]
- * @psalm-var array<string, string>
+ * @var list<string>
*/
private $fallbackDirsPsr0 = array();
@@ -78,8 +80,7 @@
private $useIncludePath = false;
/**
- * @var string[]
- * @psalm-var array<string, string>
+ * @var array<string, string>
*/
private $classMap = array();
@@ -87,29 +88,29 @@
private $classMapAuthoritative = false;
/**
- * @var bool[]
- * @psalm-var array<string, bool>
+ * @var array<string, bool>
*/
private $missingClasses = array();
- /** @var ?string */
+ /** @var string|null */
private $apcuPrefix;
/**
- * @var self[]
+ * @var array<string, self>
*/
private static $registeredLoaders = array();
/**
- * @param ?string $vendorDir
+ * @param string|null $vendorDir
*/
public function __construct($vendorDir = null)
{
$this->vendorDir = $vendorDir;
+ self::initializeIncludeClosure();
}
/**
- * @return string[]
+ * @return array<string, list<string>>
*/
public function getPrefixes()
{
@@ -121,8 +122,7 @@
}
/**
- * @return array[]
- * @psalm-return array<string, array<int, string>>
+ * @return array<string, list<string>>
*/
public function getPrefixesPsr4()
{
@@ -130,8 +130,7 @@
}
/**
- * @return array[]
- * @psalm-return array<string, string>
+ * @return list<string>
*/
public function getFallbackDirs()
{
@@ -139,8 +138,7 @@
}
/**
- * @return array[]
- * @psalm-return array<string, string>
+ * @return list<string>
*/
public function getFallbackDirsPsr4()
{
@@ -148,8 +146,7 @@
}
/**
- * @return string[] Array of classname => path
- * @psalm-return array<string, string>
+ * @return array<string, string> Array of classname => path
*/
public function getClassMap()
{
@@ -157,8 +154,7 @@
}
/**
- * @param string[] $classMap Class to filename map
- * @psalm-param array<string, string> $classMap
+ * @param array<string, string> $classMap Class to filename map
*
* @return void
*/
@@ -175,24 +171,25 @@
* Registers a set of PSR-0 directories for a given prefix, either
* appending or prepending to the ones previously set for this prefix.
*
- * @param string $prefix The prefix
- * @param string[]|string $paths The PSR-0 root directories
- * @param bool $prepend Whether to prepend the directories
+ * @param string $prefix The prefix
+ * @param list<string>|string $paths The PSR-0 root directories
+ * @param bool $prepend Whether to prepend the directories
*
* @return void
*/
public function add($prefix, $paths, $prepend = false)
{
+ $paths = (array) $paths;
if (!$prefix) {
if ($prepend) {
$this->fallbackDirsPsr0 = array_merge(
- (array) $paths,
+ $paths,
$this->fallbackDirsPsr0
);
} else {
$this->fallbackDirsPsr0 = array_merge(
$this->fallbackDirsPsr0,
- (array) $paths
+ $paths
);
}
@@ -201,19 +198,19 @@
$first = $prefix[0];
if (!isset($this->prefixesPsr0[$first][$prefix])) {
- $this->prefixesPsr0[$first][$prefix] = (array) $paths;
+ $this->prefixesPsr0[$first][$prefix] = $paths;
return;
}
if ($prepend) {
$this->prefixesPsr0[$first][$prefix] = array_merge(
- (array) $paths,
+ $paths,
$this->prefixesPsr0[$first][$prefix]
);
} else {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$this->prefixesPsr0[$first][$prefix],
- (array) $paths
+ $paths
);
}
}
@@ -222,9 +219,9 @@
* Registers a set of PSR-4 directories for a given namespace, either
* appending or prepending to the ones previously set for this namespace.
*
- * @param string $prefix The prefix/namespace, with trailing '\'
- * @param string[]|string $paths The PSR-4 base directories
- * @param bool $prepend Whether to prepend the directories
+ * @param string $prefix The prefix/namespace, with trailing '\'
+ * @param list<string>|string $paths The PSR-4 base directories
+ * @param bool $prepend Whether to prepend the directories
*
* @throws InvalidArgumentException
*
@@ -232,17 +229,18 @@
*/
public function addPsr4($prefix, $paths, $prepend = false)
{
+ $paths = (array) $paths;
if (!$prefix) {
// Register directories for the root namespace.
if ($prepend) {
$this->fallbackDirsPsr4 = array_merge(
- (array) $paths,
+ $paths,
$this->fallbackDirsPsr4
);
} else {
$this->fallbackDirsPsr4 = array_merge(
$this->fallbackDirsPsr4,
- (array) $paths
+ $paths
);
}
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
@@ -252,18 +250,18 @@
throw new InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
- $this->prefixDirsPsr4[$prefix] = (array) $paths;
+ $this->prefixDirsPsr4[$prefix] = $paths;
} elseif ($prepend) {
// Prepend directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
- (array) $paths,
+ $paths,
$this->prefixDirsPsr4[$prefix]
);
} else {
// Append directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$this->prefixDirsPsr4[$prefix],
- (array) $paths
+ $paths
);
}
}
@@ -272,8 +270,8 @@
* Registers a set of PSR-0 directories for a given prefix,
* replacing any others previously set for this prefix.
*
- * @param string $prefix The prefix
- * @param string[]|string $paths The PSR-0 base directories
+ * @param string $prefix The prefix
+ * @param list<string>|string $paths The PSR-0 base directories
*
* @return void
*/
@@ -290,8 +288,8 @@
* Registers a set of PSR-4 directories for a given namespace,
* replacing any others previously set for this namespace.
*
- * @param string $prefix The prefix/namespace, with trailing '\'
- * @param string[]|string $paths The PSR-4 base directories
+ * @param string $prefix The prefix/namespace, with trailing '\'
+ * @param list<string>|string $paths The PSR-4 base directories
*
* @throws InvalidArgumentException
*
@@ -425,7 +423,8 @@
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
- includeFile($file);
+ $includeFile = self::$includeFile;
+ $includeFile($file);
return true;
}
@@ -476,9 +475,9 @@
}
/**
- * Returns the currently registered loaders indexed by their corresponding vendor directories.
+ * Returns the currently registered loaders keyed by their corresponding vendor directories.
*
- * @return self[]
+ * @return array<string, self>
*/
public static function getRegisteredLoaders()
{
@@ -555,18 +554,26 @@
return false;
}
-}
-/**
- * Scope isolated include.
- *
- * Prevents access to $this/self from included files.
- *
- * @param string $file
- * @return void
- * @private
- */
-function includeFile($file)
-{
- include $file;
+ /**
+ * @return void
+ */
+ private static function initializeIncludeClosure()
+ {
+ if (self::$includeFile !== null) {
+ return;
+ }
+
+ /**
+ * Scope isolated include.
+ *
+ * Prevents access to $this/self from included files.
+ *
+ * @param string $file
+ * @return void
+ */
+ self::$includeFile = Closure::bind(static function($file) {
+ include $file;
+ }, null, null);
+ }
}
--- a/timetics/vendor/composer/InstalledVersions.php
+++ b/timetics/vendor/composer/InstalledVersions.php
@@ -1,352 +0,0 @@
-<?php
-
-/*
- * This file is part of Composer.
- *
- * (c) Nils Adermann <naderman@naderman.de>
- * Jordi Boggiano <j.boggiano@seld.be>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Composer;
-
-use ComposerAutoloadClassLoader;
-use ComposerSemverVersionParser;
-
-/**
- * This class is copied in every Composer installed project and available to all
- *
- * See also https://getcomposer.org/doc/07-runtime.md#installed-versions
- *
- * To require its presence, you can require `composer-runtime-api ^2.0`
- *
- * @final
- */
-class InstalledVersions
-{
- /**
- * @var mixed[]|null
- * @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
- */
- private static $installed;
-
- /**
- * @var bool|null
- */
- private static $canGetVendors;
-
- /**
- * @var array[]
- * @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
- */
- private static $installedByVendor = array();
-
- /**
- * Returns a list of all package names which are present, either by being installed, replaced or provided
- *
- * @return string[]
- * @psalm-return list<string>
- */
- public static function getInstalledPackages()
- {
- $packages = array();
- foreach (self::getInstalled() as $installed) {
- $packages[] = array_keys($installed['versions']);
- }
-
- if (1 === count($packages)) {
- return $packages[0];
- }
-
- return array_keys(array_flip(call_user_func_array('array_merge', $packages)));
- }
-
- /**
- * Returns a list of all package names with a specific type e.g. 'library'
- *
- * @param string $type
- * @return string[]
- * @psalm-return list<string>
- */
- public static function getInstalledPackagesByType($type)
- {
- $packagesByType = array();
-
- foreach (self::getInstalled() as $installed) {
- foreach ($installed['versions'] as $name => $package) {
- if (isset($package['type']) && $package['type'] === $type) {
- $packagesByType[] = $name;
- }
- }
- }
-
- return $packagesByType;
- }
-
- /**
- * Checks whether the given package is installed
- *
- * This also returns true if the package name is provided or replaced by another package
- *
- * @param string $packageName
- * @param bool $includeDevRequirements
- * @return bool
- */
- public static function isInstalled($packageName, $includeDevRequirements = true)
- {
- foreach (self::getInstalled() as $installed) {
- if (isset($installed['versions'][$packageName])) {
- return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']);
- }
- }
-
- return false;
- }
-
- /**
- * Checks whether the given package satisfies a version constraint
- *
- * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
- *
- * ComposerInstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
- *
- * @param VersionParser $parser Install composer/semver to have access to this class and functionality
- * @param string $packageName
- * @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
- * @return bool
- */
- public static function satisfies(VersionParser $parser, $packageName, $constraint)
- {
- $constraint = $parser->parseConstraints($constraint);
- $provided = $parser->parseConstraints(self::getVersionRanges($packageName));
-
- return $provided->matches($constraint);
- }
-
- /**
- * Returns a version constraint representing all the range(s) which are installed for a given package
- *
- * It is easier to use this via isInstalled() with the $constraint argument if you need to check
- * whether a given version of a package is installed, and not just whether it exists
- *
- * @param string $packageName
- * @return string Version constraint usable with composer/semver
- */
- public static function getVersionRanges($packageName)
- {
- foreach (self::getInstalled() as $installed) {
- if (!isset($installed['versions'][$packageName])) {
- continue;
- }
-
- $ranges = array();
- if (isset($installed['versions'][$packageName]['pretty_version'])) {
- $ranges[] = $installed['versions'][$packageName]['pretty_version'];
- }
- if (array_key_exists('aliases', $installed['versions'][$packageName])) {
- $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
- }
- if (array_key_exists('replaced', $installed['versions'][$packageName])) {
- $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
- }
- if (array_key_exists('provided', $installed['versions'][$packageName])) {
- $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
- }
-
- return implode(' || ', $ranges);
- }
-
- throw new OutOfBoundsException('Package "' . $packageName . '" is not installed');
- }
-
- /**
- * @param string $packageName
- * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
- */
- public static function getVersion($packageName)
- {
- foreach (self::getInstalled() as $installed) {
- if (!isset($installed['versions'][$packageName])) {
- continue;
- }
-
- if (!isset($installed['versions'][$packageName]['version'])) {
- return null;
- }
-
- return $installed['versions'][$packageName]['version'];
- }
-
- throw new OutOfBoundsException('Package "' . $packageName . '" is not installed');
- }
-
- /**
- * @param string $packageName
- * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
- */
- public static function getPrettyVersion($packageName)
- {
- foreach (self::getInstalled() as $installed) {
- if (!isset($installed['versions'][$packageName])) {
- continue;
- }
-
- if (!isset($installed['versions'][$packageName]['pretty_version'])) {
- return null;
- }
-
- return $installed['versions'][$packageName]['pretty_version'];
- }
-
- throw new OutOfBoundsException('Package "' . $packageName . '" is not installed');
- }
-
- /**
- * @param string $packageName
- * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
- */
- public static function getReference($packageName)
- {
- foreach (self::getInstalled() as $installed) {
- if (!isset($installed['versions'][$packageName])) {
- continue;
- }
-
- if (!isset($installed['versions'][$packageName]['reference'])) {
- return null;
- }
-
- return $installed['versions'][$packageName]['reference'];
- }
-
- throw new OutOfBoundsException('Package "' . $packageName . '" is not installed');
- }
-
- /**
- * @param string $packageName
- * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
- */
- public static function getInstallPath($packageName)
- {
- foreach (self::getInstalled() as $installed) {
- if (!isset($installed['versions'][$packageName])) {
- continue;
- }
-
- return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
- }
-
- throw new OutOfBoundsException('Package "' . $packageName . '" is not installed');
- }
-
- /**
- * @return array
- * @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
- */
- public static function getRootPackage()
- {
- $installed = self::getInstalled();
-
- return $installed[0]['root'];
- }
-
- /**
- * Returns the raw installed.php data for custom implementations
- *
- * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
- * @return array[]
- * @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
- */
- public static function getRawData()
- {
- @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
-
- if (null === self::$installed) {
- // only require the installed.php file if this file is loaded from its dumped location,
- // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
- if (substr(__DIR__, -8, 1) !== 'C') {
- self::$installed = include __DIR__ . '/installed.php';
- } else {
- self::$installed = array();
- }
- }
-
- return self::$installed;
- }
-
- /**
- * Returns the raw data of all installed.php which are currently loaded for custom implementations
- *
- * @return array[]
- * @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
- */
- public static function getAllRawData()
- {
- return self::getInstalled();
- }
-
- /**
- * Lets you reload the static array from another file
- *
- * This is only useful for complex integrations in which a project needs to use
- * this class but then also needs to execute another project's autoloader in process,
- * and wants to ensure both projects have access to their version of installed.php.
- *
- * A typical case would be PHPUnit, where it would need to make sure it reads all
- * the data it needs from this class, then call reload() with
- * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
- * the project in which it runs can then also use this class safely, without
- * interference between PHPUnit's dependencies and the project's dependencies.
- *
- * @param array[] $data A vendor/composer/installed.php data set
- * @return void
- *
- * @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
- */
- public static function reload($data)
- {
- self::$installed = $data;
- self::$installedByVendor = array();
- }
-
- /**
- * @return array[]
- * @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
- */
- private static function getInstalled()
- {
- if (null === self::$canGetVendors) {
- self::$canGetVendors = method_exists('ComposerAutoloadClassLoader', 'getRegisteredLoaders');
- }
-
- $installed = array();
-
- if (self::$canGetVendors) {
- foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
- if (isset(self::$installedByVendor[$vendorDir])) {
- $installed[] = self::$installedByVendor[$vendorDir];
- } elseif (is_file($vendorDir.'/composer/installed.php')) {
- $installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
- if (null === self::$installed && strtr($vendorDir.'/composer', '\', '/') === strtr(__DIR__, '\', '/')) {
- self::$installed = $installed[count($installed) - 1];
- }
- }
- }
- }
-
- if (null === self::$installed) {
- // only require the installed.php file if this file is loaded from its dumped location,
- // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
- if (substr(__DIR__, -8, 1) !== 'C') {
- self::$installed = require __DIR__ . '/installed.php';
- } else {
- self::$installed = array();
- }
- }
- $installed[] = self::$installed;
-
- return $installed;
- }
-}
--- a/timetics/vendor/composer/autoload_psr4.php
+++ b/timetics/vendor/composer/autoload_psr4.php
@@ -6,5 +6,4 @@
$baseDir = dirname($vendorDir);
return array(
- 'UninstallerForm\' => array($vendorDir . '/themewinter/uninstaller_form/src'),
);
--- a/timetics/vendor/composer/autoload_real.php
+++ b/timetics/vendor/composer/autoload_real.php
@@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer
-class ComposerAutoloaderInit05cd069eafe0df94d6f2b539707d0acb
+class ComposerAutoloaderInitd02707597fbf5927c7666b74bdb40ea9
{
private static $loader;
@@ -22,12 +22,12 @@
return self::$loader;
}
- spl_autoload_register(array('ComposerAutoloaderInit05cd069eafe0df94d6f2b539707d0acb', 'loadClassLoader'), true, true);
+ spl_autoload_register(array('ComposerAutoloaderInitd02707597fbf5927c7666b74bdb40ea9', 'loadClassLoader'), true, true);
self::$loader = $loader = new ComposerAutoloadClassLoader(dirname(__DIR__));
- spl_autoload_unregister(array('ComposerAutoloaderInit05cd069eafe0df94d6f2b539707d0acb', 'loadClassLoader'));
+ spl_autoload_unregister(array('ComposerAutoloaderInitd02707597fbf5927c7666b74bdb40ea9', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
- call_user_func(ComposerAutoloadComposerStaticInit05cd069eafe0df94d6f2b539707d0acb::getInitializer($loader));
+ call_user_func(ComposerAutoloadComposerStaticInitd02707597fbf5927c7666b74bdb40ea9::getInitializer($loader));
$loader->register(true);
--- a/timetics/vendor/composer/autoload_static.php
+++ b/timetics/vendor/composer/autoload_static.php
@@ -4,22 +4,8 @@
namespace ComposerAutoload;
-class ComposerStaticInit05cd069eafe0df94d6f2b539707d0acb
+class ComposerStaticInitd02707597fbf5927c7666b74bdb40ea9
{
- public static $prefixLengthsPsr4 = array (
- 'U' =>
- array (
- 'UninstallerForm\' => 16,
- ),
- );
-
- public static $prefixDirsPsr4 = array (
- 'UninstallerForm\' =>
- array (
- 0 => __DIR__ . '/..' . '/themewinter/uninstaller_form/src',
- ),
- );
-
public static $classMap = array (
'Composer\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
);
@@ -27,9 +13,7 @@
public static function getInitializer(ClassLoader $loader)
{
return Closure::bind(function () use ($loader) {
- $loader->prefixLengthsPsr4 = ComposerStaticInit05cd069eafe0df94d6f2b539707d0acb::$prefixLengthsPsr4;
- $loader->prefixDirsPsr4 = ComposerStaticInit05cd069eafe0df94d6f2b539707d0acb::$prefixDirsPsr4;
- $loader->classMap = ComposerStaticInit05cd069eafe0df94d6f2b539707d0acb::$classMap;
+ $loader->classMap = ComposerStaticInitd02707597fbf5927c7666b74bdb40ea9::$classMap;
}, null, ClassLoader::class);
}
--- a/timetics/vendor/composer/installed.php
+++ b/timetics/vendor/composer/installed.php
@@ -1,34 +0,0 @@
-<?php return array(
- 'root' => array(
- 'name' => 'arraytics/timetics',
- 'pretty_version' => 'dev-develop',
- 'version' => 'dev-develop',
- 'reference' => '239996d381e93f1cbde0bb13231b7fdae22611dd',
- 'type' => 'library',
- 'install_path' => __DIR__ . '/../../',
- 'aliases' => array(),
- 'dev' => true,
- ),
- 'versions' => array(
- 'arraytics/timetics' => array(
- 'pretty_version' => 'dev-develop',
- 'version' => 'dev-develop',
- 'reference' => '239996d381e93f1cbde0bb13231b7fdae22611dd',
- 'type' => 'library',
- 'install_path' => __DIR__ . '/../../',
- 'aliases' => array(),
- 'dev_requirement' => false,
- ),
- 'themewinter/uninstaller_form' => array(
- 'pretty_version' => 'dev-main',
- 'version' => 'dev-main',
- 'reference' => '2d3d0609af9f42679225ee7e4262c6d0c5272e38',
- 'type' => 'library',
- 'install_path' => __DIR__ . '/../themewinter/uninstaller_form',
- 'aliases' => array(
- 0 => '9999999-dev',
- ),
- 'dev_requirement' => false,
- ),
- ),
-);
--- a/timetics/vendor/themewinter/uninstaller_form/config/google-sheet.php
+++ b/timetics/vendor/themewinter/uninstaller_form/config/google-sheet.php
@@ -1,6 +0,0 @@
-<?php
-
-//Spread Sheet id you will get after sharing the sheet with everyone and giving editable permission.
-return [
- 'spreadsheet_id' => '1QIc7cA4cJIgK048FhhV7qds-mjMIhsEPyl9I84Stzm8',
-];
--- a/timetics/vendor/themewinter/uninstaller_form/src/Api/FeedbackController.php
+++ b/timetics/vendor/themewinter/uninstaller_form/src/Api/FeedbackController.php
@@ -1,189 +0,0 @@
-<?php
-namespace UninstallerFormApi;
-
-use WP_REST_Request;
-
-/**
- * Feedback controller for the uninstaller form.
- *
- * @since 1.0.0
- *
- * @package UNINSTALLER_FORM
- */
-class FeedbackController {
- protected $plugin_file;
- protected $plugin_text_domain;
- protected $plugin_name;
- protected $plugin_slug;
-
- /**
- * Store namespace
- *
- * @since 1.0.0
- *
- * @var string
- */
- protected $namespace;
-
- /**
- * Store rest base
- *
- * @since 1.0.0
- *
- * @var string
- */
- protected $rest_base = 'feedback';
-
- /**
- * FeedbackController Constructor.
- *
- * @param string $plugin_file The path to the plugin file.
- * @param string $plugin_text_domain The text domain of the plugin.
- * @param string $plugin_name The name of the plugin.
- * @param string $plugin_slug The slug of the plugin.
- *
- * @since 1.0.0
- */
- public function __construct($plugin_file, $plugin_text_domain, $plugin_name, $plugin_slug) {
- $this->plugin_file = $plugin_file;
- $this->plugin_text_domain = $plugin_text_domain;
- $this->plugin_name = $plugin_name;
- $this->plugin_slug = $plugin_slug;
- $this->namespace = $plugin_slug . '/v1';
- $this->register_routes();
- }
-
- /**
- * Register REST routes for the feedback controller.
- *
- * @since 1.0.0
- *
- * @return void
- */
- protected function register_routes() {
- register_rest_route($this->namespace, $this->rest_base, [
- 'methods' => 'POST',
- 'callback' => [$this, 'handle_feedback'],
- 'permission_callback' => function () {
- return current_user_can('manage_options');
- },
- ]);
- }
-
- /**
- * Handle feedback submission.
- *
- * @since 1.0.0
- *
- * @param WP_REST_Request $request The request object.
- * @return WP_REST_Response The response object.
- */
- public function handle_feedback(WP_REST_Request $request) {
- $nonce = $request->get_header('X-WP-Nonce');
- if (! wp_verify_nonce($nonce, 'wp_rest')) {
- return rest_ensure_response([
- 'status_code' => 403,
- 'success' => 0,
- 'message' => 'Invalid nonce. Unauthorized request.',
- ]);
- }
-
- $data = $request->get_json_params();
- $feedback = ! empty($data['feedback']) ? sanitize_text_field($data['feedback']) : 'No feedback';
- $reasons = ! empty($data['reasons']) ? sanitize_text_field($data['reasons']) : 'No reasons';
- $customer_email = is_email($data['email']) ? sanitize_email($data['email']) : '';
- $theme_name = ! empty($data['theme_name']) ? sanitize_text_field($data['theme_name']) : '';
-
- if (! $this->verify_email_status($customer_email)) {
- $customer_email = '';
- }
-
- // Get current user info
- $current_user = wp_get_current_user();
- $customer_name = $current_user->exists() ? $current_user->display_name : 'Guest';
-
- try {
- // $config = include plugin_dir_path($this->plugin_file) . 'vendor/themewinter/uninstaller_form/config/google-sheet.php';
- // $spreadsheetId = $config['spreadsheet_id'] ?? '';
-
- // $credentialsPath = plugin_dir_path($this->plugin_file) . 'vendor/themewinter/uninstaller_form/config/google-credentials.json';
-
- $sheetName = str_replace(' ', '_', $this->plugin_name);
-
- if (! empty($customer_email) && ! empty($reasons)) {
-
- $feedback_response = wp_remote_post('https://products.arraytics.com/feedback/wp-json/afp/v1/feedback', [
- 'method' => 'POST',
- 'headers' => [
- 'Content-Type' => 'application/json',
- ],
- 'body' => json_encode([
- 'customer_name' => $customer_name,
- 'feedback' => $feedback,
- 'customer_email' => $customer_email,
- 'plugin_name' => $this->plugin_name,
- 'theme' => $theme_name,
- 'reason' => explode(',',$reasons)
- ]),
- ]);
-
-
- //Storing data to excell sheet
- // $sheetClient = new UninstallerFormSupportGoogleSheetClient($credentialsPath, $spreadsheetId, $sheetName);
- // $sheetClient->appendRow([
- // $customer_name, // Customer name
- // $customer_email, // Customer email
- // $this->plugin_name, // Plugin Slug
- // $reasons, // Reason
- // $feedback, // Feedback message,
- // $theme_name, // Theme name
- // current_time('mysql'), // Timestamp
- // ]);
-
- //Send data through webhook
- $webhook = "https://themewinter.com/?fluentcrm=1&route=contact&hash=50d358fa-e039-4459-a3d0-ef73b3c7d451";
- $body = [
- 'customer_name' => $customer_name,
- 'email' => $customer_email,
- 'plugin_name' => $this->plugin_name,
- 'reason' => $reasons,
- 'feedback' => $feedback,
- 'theme_name' => $theme_name,
- ];
- $webhook_response = wp_remote_post($webhook, ['body' => $body]);
- }
- } catch (Exception $e) {
- return rest_ensure_response([
- 'status_code' => 500,
- 'success' => 0,
- 'message' => 'Unable to store feedback.',
- ]);
- }
-
- return rest_ensure_response([
- 'status_code' => 200,
- 'success' => 1,
- 'message' => 'Feedback saved successfully.',
- ]);
- }
-
- public function verify_email_status(string $email = "") {
- $api_key = '700tpaQtc06FcqN93Ljkoibz6oo76KWk'; // Replace with your actual API key
- $url = 'https://emailverifier.reoon.com/api/v1/verify';
-
- $response = wp_remote_get(add_query_arg([
- 'email' => $email,
- 'key' => $api_key,
- 'mode' => 'quick',
- ], $url));
-
- if (is_wp_error($response)) {
- return 'error';
- }
-
- $body = wp_remote_retrieve_body($response);
- $data = json_decode($body, true);
-
- return isset($data['status']) && $data['status'] === "valid";
- }
-}
No newline at end of file
--- a/timetics/vendor/themewinter/uninstaller_form/src/HookRegistrar.php
+++ b/timetics/vendor/themewinter/uninstaller_form/src/HookRegistrar.php
@@ -1,53 +0,0 @@
-<?php
-namespace UninstallerForm;
-
-use UninstallerFormApiFeedbackController;
-use UninstallerFormSupportLocalizer;
-
-/**
- * HookRegistrar class for the uninstaller form.
- *
- * @since 1.0.0
- *
- * @package UNINSTALLER_FORM
- */
-class HookRegistrar {
- protected $plugin_name, $plugin_slug, $plugin_file, $plugin_text_domain, $script_handler;
-
- /**
- * HookRegistrar Constructor.
- *
- * @param string $plugin_name The name of the plugin.
- * @param string $plugin_slug The slug of the plugin.
- * @param string $plugin_file The path to the plugin file.
- * @param string $plugin_text_domain The text domain of the plugin.
- * @param string $script_handler The handle of the scri