diff --git a/src/README.txt b/src/README.txt old mode 100755 new mode 100644 index 94ae9074..2cf9be90 --- a/src/README.txt +++ b/src/README.txt @@ -49,13 +49,13 @@ This WordPress plugin can be found at [wordpress.org/plugins/toplytics/](https:/ Alternatively, go into your WordPress dashboard and click on *Plugins -> Add Plugin* and search for Toplytics. Then click on *Install*, then on *Activate Now*. -We offer two possibilities to use Toplytics: through **Public Authorization** or the **Private Authorization**, for more configuration details check [Toplytics installation](https://www.presslabs.com/code/toplytics/installation/). +We offer two possibilities to use Toplytics: through **Quick Connect** or the **Manual Connect**, for more configuration details check [Toplytics installation](https://www.presslabs.com/code/toplytics/installation/). -The **Public Authorization** method is using the Presslabs public API key to authenticate you to the Google Analytics API, and you don't have to set up your own API keys. To use this method, simply press the **Log in with your Google Account via Presslabs.org** button and you will be redirected to the Google Authorization screen where you will be asked for read access to your analytics profiles. +The **Quick Connect** method is using the Presslabs public API key to authenticate you to the Google Analytics API, and you don't have to set up your own API keys. To use this method, simply press the **Log in with your Google Account via Presslabs.org** button and you will be redirected to the Google Authorization screen where you will be asked for read access to your analytics profiles. Then you need to select your profile and you are all set. -The private authorization is the recommended way in using Toplytics, as it offers you complete control over the connection by using your very own API keys and application for granting access. +The manual connect is the recommended way in using Toplytics, as it offers you complete control over the connection by using your very own API keys and application for granting access. You need to enter your Client ID and Client Secret from your Google Analytics account. The next steps will guide you in configuring your Google Analytics account to Toplytics. Keep in mind that you will need the **Redirect URL** mentioned in this page further in configuring Toplytics. @@ -70,14 +70,14 @@ In this step please register a new client application with Google. To register a After you set up your product name, you can create your credentials. Go back to the **Dashboard** section, click on the arrow of the button **Create credentials** and choose the **OAuth Client ID** option. -When asked to choose your application type choose the **Web application** option. You will be asked to introduce the **Javascript Origins** and **Redirects URI's**. As **Authorized JavaScipt Origins** introduce your domain name, and as **Authorized redirect URI** you need to introduce the Redirect URL from `Settings -> Toplytics -> Private Authorization`. +When asked to choose your application type choose the **Web application** option. You will be asked to introduce the **Javascript Origins** and **Redirects URI's**. As **Authorized JavaScipt Origins** introduce your domain name, and as **Authorized redirect URI** you need to introduce the Redirect URL from `Settings -> Toplytics -> Manual Connect`. Your newly created credentials will appear on the **Credentials** page and the **Client ID** and **Client secret** you need to authorize the **Private Authentification** will appear in a pop up. You can also see them by pressing the **Edit OAuth Client** button from the Credentials section. = Configuration step 2 = In this step you will need to authorize requests. -1. Copy the Client ID and the Client Secret keys from the **Credentials section**, then go back to `Settings -> Toplytics -> Private Authorization` to paste these credentials. By using these keys the client application will avoid sharing the username and/or password with any other Toplytics users. +1. Copy the Client ID and the Client Secret keys from the **Credentials section**, then go back to `Settings -> Toplytics -> Manual Connect` to paste these credentials. By using these keys the client application will avoid sharing the username and/or password with any other Toplytics users. 2. Click the **Private Authorize** button and after logging in you need to agree that the newly created app will access your Analytics data and you are all set. diff --git a/src/components/Activator.php b/src/components/Activator.php index f1f08a8c..3f002f73 100755 --- a/src/components/Activator.php +++ b/src/components/Activator.php @@ -105,9 +105,9 @@ public static function addDefaultOptions() $options = [ 'toplytics_results_ranges' => [ - 'month' => date_i18n('Y-m-d', strtotime('-29 days')), - 'week' => date_i18n('Y-m-d', strtotime('-6 days')), - 'today' => date_i18n('Y-m-d', strtotime('today')), + 'month' => '30daysAgo', + 'week' => '7daysAgo', + 'today' => 'yesterday', 'realtime' => 0, ], 'toplytics_private_auth_config' => false, diff --git a/src/components/Backend.php b/src/components/Backend.php index 3c27da8e..0937dd1a 100755 --- a/src/components/Backend.php +++ b/src/components/Backend.php @@ -5,9 +5,20 @@ use Exception; use Google\Client; use Toplytics\Activator; -use Google\Service\Analytics; +use Google\Service\AnalyticsData; use GuzzleHttp\Exception\RequestException; use Google\Service\Exception as GoogleServiceException; +use Google\Analytics\Data\V1beta\BetaAnalyticsDataClient; + +use Google\Service\AnalyticsData\DateRange as Google_Service_AnalyticsData_DateRange; +use Google\Service\AnalyticsData\Dimension as Google_Service_AnalyticsData_Dimension; +use Google\Service\AnalyticsData\Metric as Google_Service_AnalyticsData_Metric; +use Google\Service\AnalyticsData\OrderBy as Google_Service_AnalyticsData_OrderBy; +use Google\Service\AnalyticsData\RunReportRequest as Google_Service_AnalyticsData_RunReportRequest; +use Google\Service\AnalyticsData\FilterExpression as Google_Service_AnalyticsData_FilterExpression; +use Google\Service\AnalyticsData\Filter as Google_Service_AnalyticsData_Filter; +use Google\Service\AnalyticsData\StringFilter as Google_Service_AnalyticsData_StringFilter; +use Google\Service\AnalyticsData\MetricOrderBy as Google_Service_AnalyticsData_MetricOrderBy; /** * The admin-specific functionality of the plugin. @@ -59,6 +70,8 @@ class Backend private $service; private $settings; + private $use_ga4; + private $_need_additional_posts_data; private $_widgets; private $_gapi_errors_count; @@ -79,6 +92,8 @@ public function __construct($plugin_basename, $version, Window $window, $setting $this->window = $window; + $this->checkAndUpdateDB(); + // TODO: This should become it's own class in the future $this->settings = $settings ?: get_option('toplytics_settings', null); @@ -96,6 +111,11 @@ public function __construct($plugin_basename, $version, Window $window, $setting */ $this->_need_additional_posts_data = false; + /** + * We default to GAv4, but we can also support UA. + */ + $this->use_ga4 = get_option('toplytics_use_ga4', true); + /** * Initialize the list of Toplytics widgets data as null. */ @@ -113,6 +133,65 @@ public function __construct($plugin_basename, $version, Window $window, $setting } } + /** + * Checks current and older version of toplytics TOPLYTICS_DB_VERSION + * + * @return int + */ + public function checkAndUpdateDB() { + $db_version = get_option('toplytics_db_version'); + + // if db_version is empty, set it to current version + if (empty($db_version)) { + $db_version = '1.0.0'; + update_option('toplytics_db_version', $this->version); + } + + // same version, no updates required + if (version_compare($db_version, $this->version, '==')) { + return 0; + } + + // we run our updates + $updates = $this->runDBUpdates($this->version); + + update_option('toplytics_db_version', $this->version); + + return $updates; + } + + /** + * This will run DB updates and return the number of updates ran + * + * @param int $version + * + * @return int + */ + public function runDBUpdates($version) { + + $updates = 0; + + $alreadyApplied = get_option('toplytics_db_updates_applied', []); + + switch ($version) { + case '4.1.0': + if (in_array('4.1.0', $alreadyApplied)) break; + + update_option('toplytics_results_ranges', [ + 'month' => '30daysAgo', + 'week' => '7daysAgo', + 'today' => 'yesterday', + 'realtime' => 0, + ]); + + update_option('toplytics_db_updates_applied', array_merge($alreadyApplied, ['4.1.0'])); + + $updates++; + } + + return $updates; + } + private function _increment_gapi_errors_count() { update_option('toplytics_gapi_errors_count', $this->_gapi_errors_count++); return $this; @@ -302,7 +381,7 @@ protected function initService() try { if ($this->serviceConnect()) { - return new Analytics($this->client); + return new AnalyticsData($this->client); } } catch (GoogleServiceException $e) { $this->window->notifyAdmins('error', __( @@ -314,6 +393,32 @@ protected function initService() return false; } + public function useGA4() { + if (empty($_POST['ToplyticsUseGA4'])) { + return; + } + + update_option('toplytics_use_ga4', true, true); + + $this->window->successRedirect(__( + 'You have switched to use Google Analytics v4!', + TOPLYTICS_DOMAIN + )); + } + + public function useUA() { + if (empty($_POST['ToplyticsUseUA'])) { + return; + } + + update_option('toplytics_use_ga4', false, true); + + $this->window->successRedirect(__( + 'You have switched to use Universal Analytics!', + TOPLYTICS_DOMAIN + )); + } + /** * This is the place where we disconnect from the Google Services * by simply forgoting the options and pinging Google to revoke the token. @@ -342,6 +447,7 @@ public function serviceDisconnect($programatic = false, $silent = false) update_option('toplytics_private_auth_config', false); update_option('toplytics_google_token', false); update_option('toplytics_profile_data', false); + update_option('toplytics_property_id', false); update_option('toplytics_auth_config', false); update_option('toplytics_auth_code', false); @@ -489,7 +595,7 @@ public function initSettings() ] ); - // Enable Daily Fetch + // // Enable Daily Fetch add_settings_field( 'fetch_today', $this->getLabel(__('Daily Top', TOPLYTICS_DOMAIN), 'fetch_today'), @@ -502,7 +608,7 @@ public function initSettings() ] ); - // Enable Realtime Fetch + // // Enable Realtime Fetch add_settings_field( 'fetch_realtime', $this->getLabel(__('Realtime Top', TOPLYTICS_DOMAIN), 'fetch_realtime'), @@ -511,7 +617,8 @@ public function initSettings() 'toplytics_settings', [ 'id' => 'fetch_realtime', - 'tooltip' => __('Enables the fetch of the most visited posts in realtime from Google Analytics in the local DB. Default: Disabled', TOPLYTICS_DOMAIN), + 'tooltip' => __('This feature is currently unavailable. We are working on it and will release it soon. Default: Disabled', TOPLYTICS_DOMAIN), + 'disabled' => true, ] ); @@ -789,6 +896,7 @@ public function switchProfile() check_admin_referer('toplytics-settings'); update_option('toplytics_profile_data', false); + update_option('toplytics_property_id', false); $this->window->successRedirect(__('Ok. Go ahead and select another profile.', TOPLYTICS_DOMAIN)); } @@ -802,10 +910,24 @@ public function switchProfile() */ public function profileSelect() { - if (empty($_POST['ToplyticsProfileSelect']) || empty($_POST['profile_id'])) { + if (empty($_POST['ToplyticsProfileSelect']) || (empty($_POST['profile_id']) && empty($_POST['property_id']))) { return false; } + if ($this->use_ga4) { + $property_id = filter_input(INPUT_POST, 'property_id', FILTER_VALIDATE_INT); + + if (!$property_id) $this->window->errorRedirect(__('Invalid property ID. Please use a valid one!', TOPLYTICS_DOMAIN)); + + update_option('toplytics_property_id', $property_id); + } else { + $this->finish_setup_for_ua(); + } + + $this->window->successRedirect(__('Well done. You have selected your analytics profile.', TOPLYTICS_DOMAIN)); + } + + protected function finish_setup_for_ua() { foreach ($this->getProfilesList() as $profile_id => $profile_info) { if ($_POST['profile_id'] == $profile_id) { update_option( @@ -821,8 +943,6 @@ public function profileSelect() break; } } - - $this->window->successRedirect(__('Well done. You have selected your analytics profile.', TOPLYTICS_DOMAIN)); } /** @@ -835,16 +955,33 @@ public function profileSelect() * @param array $updated_settings The updated set of settings * @return array The updated settings, after processing */ - public function act_before_settings_update( $updated_settings ) { + public function act_before_settings_update($updated_settings) + { // Fetch the current set of Toplytics settings from the DB. - $current_settings = get_option( 'toplytics_settings' ); + $current_settings = get_option('toplytics_settings'); + + $settings_to_check = [ + 'include_featured_image_in_json', + 'custom_featured_image_size', + 'allowed_post_types', + 'ignore_posts_ids', + ]; + + $trigger = false; + + foreach ($settings_to_check as $setting) { + if (!isset($updated_settings[$setting]) || !isset($current_settings[$setting])) continue; + + if ($updated_settings[$setting] != $current_settings[$setting]) { + $trigger = true; + break; + } + } + // If certain settings have changed, trigger an update of the analytics data. - if ( ( $updated_settings['include_featured_image_in_json'] != $current_settings['include_featured_image_in_json'] ) || - ( $updated_settings['custom_featured_image_size'] != $current_settings['custom_featured_image_size'] ) || - ( $updated_settings['allowed_post_types'] != $current_settings['allowed_post_types'] ) || - ( $updated_settings['ignore_posts_ids'] != $current_settings['ignore_posts_ids'] ) ) { + if ($trigger) { // Schedule a late call for updating the analytics data. - add_action( 'shutdown', array( $this, 'updateAnalyticsDataOnSettingsUpdate' ) ); + add_action('shutdown', array($this, 'updateAnalyticsDataOnSettingsUpdate')); } return $updated_settings; @@ -880,8 +1017,7 @@ public function updateAnalyticsData() // Do an initial fetch of the regular GA stats and store them in the database. $is_updated += $this->updateAnalyticsDataResults(); - // Do an initial fetch of the realtime GA stats and store them in the database. - $is_updated += $this->updateAnalyticsRealTimeDataResults(); + // $is_updated += $this->updateAnalyticsRealTimeDataResults(); // Maybe also update category posts data and top posts data. if ( $this->_need_additional_posts_data ) { @@ -896,9 +1032,6 @@ public function updateAnalyticsData() return $is_updated; } - - - /** * We update our database with the latest data from GA. * We do 2 separate data fetchings for normal data and realtime @@ -1144,71 +1277,88 @@ private function getAnalyticsRealTimeData( $extended_fetch = false ) */ private function getAnalyticsData( $extended_fetch = false ) { - $optParams = [ - 'quotaUser' => md5(home_url()), - 'dimensions' => 'ga:pagePath', - 'sort' => '-ga:pageviews', - 'max-results' => $this->checkSetting('max_posts_fetch_limit') ? (int)$this->settings['max_posts_fetch_limit'] : TOPLYTICS_MAX_RESULTS, - ]; + $propertyId = get_option('toplytics_property_id', false); + + if (!$propertyId) return false; + + $propertyId = 'properties/'.$propertyId; + + $is_updated = 0; + + $dimension = new Google_Service_AnalyticsData_Dimension([ + 'name' => 'pagePath', + ]); + + $metric = new Google_Service_AnalyticsData_Metric([ + 'name' => 'eventCount', + ]); + + $orderMetric = new Google_Service_AnalyticsData_MetricOrderBy(); + $orderMetric->setMetricName('eventCount'); + + $orderBy = new Google_Service_AnalyticsData_OrderBy(); + $orderBy->setMetric($orderMetric); + $orderBy->setDesc(true); + + $limit = $this->checkSetting('max_posts_fetch_limit') ? (int)$this->settings['max_posts_fetch_limit'] : TOPLYTICS_MAX_RESULTS; if ( $extended_fetch ) { // Retrieve extra posts. - $optParams['max-results'] += TOPLYTICS_NUM_EXTRA_RESULTS; + $limit += TOPLYTICS_NUM_EXTRA_RESULTS; } - + + // Fetch results ranges from option. Create the option, if it does not exist. + $results_ranges = get_option( 'toplytics_results_ranges', false ); + if ( ! $results_ranges ) { + Activator::addDefaultOptions(); + // Fetch the option, once again; it is now initialized. + $results_ranges = get_option( 'toplytics_results_ranges' ); + } + $result = []; - $profile_id = get_option('toplytics_profile_data')['profile_id']; - if ($profile_id) { - // Fetch results ranges from option. Create the option, if it does not exist. - $results_ranges = get_option( 'toplytics_results_ranges', false ); - if ( ! $results_ranges ) { - Activator::addDefaultOptions(); - // Fetch the option, once again; it is now initialized. - $results_ranges = get_option( 'toplytics_results_ranges' ); - } - // update dates! - $results_ranges = [ - 'month' => date_i18n('Y-m-d', strtotime('-29 days')), - 'week' => date_i18n('Y-m-d', strtotime('-6 days')), - 'today' => date_i18n('Y-m-d', strtotime('today')), - 'realtime' => 0, - ]; - - foreach ( $results_ranges as $when => $start_date ) { - // We make sure fetching is enabled in settings - if ( ! $start_date || ! $this->checkSetting( 'fetch_' . $when ) ) { - continue; - } + foreach ( $results_ranges as $when => $start_date ) { - $filters = apply_filters('toplytics_analytics_filters', '', $when, 'ga:pageviews'); - if (! empty($filters)) { - $optParams['filters'] = $filters; - } - $data = $this->service->data_ga->get( - 'ga:' . $profile_id, - $start_date, - date_i18n('Y-m-d', time()), - 'ga:pageviews', - $optParams - ); - apply_filters( - 'toplytics_analytics_data', - $when, - $data->selfLink, - $data->modelData['query'], - $data->modelData['profileId'] - ); - $result[ $when ] = []; - if ($data->rows) { - foreach ($data->rows as $item) { - $result[ $when ][ $item[0] ] = $item[1]; - } - } + // We make sure fetching is enabled in settings + if ( ! $start_date || ! $this->checkSetting( 'fetch_' . $when ) ) { + continue; + } - apply_filters('toplytics_analytics_data_result', $result[ $when ], $when); + $dateRange = new Google_Service_AnalyticsData_DateRange([ + 'start_date' => $start_date, + 'end_date' => apply_filters('toplytics_end_date', 'today', $when, $start_date) + ]); + + $request = new Google_Service_AnalyticsData_RunReportRequest( apply_filters('toplytics_analytics_params_v4', [ + 'property' => $propertyId, + 'date_ranges' => [$dateRange], + 'dimensions' => [$dimension], + 'metrics' => [$metric], + 'limit' => $limit, + 'dimension_filter' => new Google_Service_AnalyticsData_FilterExpression([ + 'filter' => new Google_Service_AnalyticsData_Filter([ + 'field_name' => 'eventName', + 'string_filter' => new Google_Service_AnalyticsData_StringFilter([ + 'value' => 'page_view', + ]), + ]), + ]), + 'order_bys' => [$orderBy], + ], $when, $start_date)); + + $response = $this->service->properties->runReport($propertyId, $request); + + $result[ $when ] = []; + + if ($response) { + foreach ($response->getRows() as $row) { + $result[ $when ][ $row->getDimensionValues()[0]->getValue() ] = $row->getMetricValues()[0]->getValue(); + } } + + apply_filters('toplytics_analytics_data_result', $result[ $when ], $when); } + return apply_filters('toplytics_analytics_data_allresults', $result); } @@ -1374,7 +1524,7 @@ protected function serviceConnect() } try { - $accessToken = $this->client->authenticate($authCode); + $accessToken = $this->client->fetchAccessTokenWithAuthCode($authCode); if (isset($accessToken['error']) && $accessToken['error']) { update_option('toplytics_auth_code', false); @@ -1457,7 +1607,7 @@ public function openWindowToSettingsView() $profiles = false; - if (!$profile) { + if (!$profile && !$this->use_ga4) { $profiles = $this->getProfilesList(); } @@ -1479,6 +1629,9 @@ public function openWindowToSettingsView() } } + $use_ga4 = $this->use_ga4; + $property_id = get_option('toplytics_property_id', false); + include $this->window->getView( 'backend.settings' ); return; @@ -1636,7 +1789,7 @@ public function decodeGoogleConfig($config = '') /** * Decoding the actual JSON config file we read from - * the presslabs.org site for public authorization. + * the presslabs.org site for quick connect. * * @since 4.0.0 * @param string $config The JSON content to be decoded @@ -1659,7 +1812,7 @@ public function decodeConfig($config = '') /** * This is the place where we arrive after pressing the - * Public Authorization button. Here we redirect the user + * Quick Connect button. Here we redirect the user * to the Public Google page. * * @return Redirect Redirect to Google Authorization @@ -1752,6 +1905,7 @@ public function isDirtyAuth() $options = [ 'toplytics_private_auth_config', 'toplytics_profile_data', + 'toplytics_property_id', 'toplytics_auth_config', 'toplytics_google_token', 'toplytics_auth_code', diff --git a/src/components/Engine.php b/src/components/Engine.php index 79de8d9f..c9e0304a 100755 --- a/src/components/Engine.php +++ b/src/components/Engine.php @@ -139,6 +139,8 @@ private function defineAdminHooks() $this->loader->addAction('admin_init', $plugin_admin, 'privateAuthorization'); $this->loader->addAction('admin_init', $plugin_admin, 'checkAuthorization'); $this->loader->addAction('admin_init', $plugin_admin, 'serviceDisconnect'); + $this->loader->addAction('admin_init', $plugin_admin, 'useGA4'); + $this->loader->addAction('admin_init', $plugin_admin, 'useUA'); $this->loader->addAction('admin_init', $plugin_admin, 'profileSelect'); $this->loader->addAction('admin_init', $plugin_admin, 'switchProfile'); $this->loader->addAction('admin_init', $plugin_admin, 'initSettings'); diff --git a/src/components/Frontend.php b/src/components/Frontend.php index dd7db9b6..9c3108d3 100755 --- a/src/components/Frontend.php +++ b/src/components/Frontend.php @@ -282,10 +282,11 @@ public function registerWidget() public function restApiInit() { if ($this->checkSetting('enable_rest_endpoint')) { - register_rest_route('toplytics/', 'results', array( + register_rest_route('toplytics', '/results/', array( - 'methods' => 'GET', + 'methods' => \WP_REST_Server::READABLE, 'callback' => [$this, 'toplyticsMasterApiEndpoint'], + 'permission_callback' => '__return_true', )); } } diff --git a/src/components/Widget.php b/src/components/Widget.php index 8b18b5a9..debb45a0 100755 --- a/src/components/Widget.php +++ b/src/components/Widget.php @@ -82,8 +82,17 @@ private function realtimeScriptArgs($args) */ public function widget($args, $instance) { + ob_start(); + $title = ''; + $period = 'week'; + $numberposts = 20; + $showviews = 0; + $loadViaJS = 0; + $category = 0; + $fallback_not_enough_ga_posts = 'recent'; + extract($args); extract($instance); @@ -147,6 +156,10 @@ public function widget($args, $instance) } if ($loadViaJS && ($this->frontend->checkSetting('enable_json') || $this->frontend->checkSetting('enable_rest_endpoint'))) { + + // make sure id is defined + $widget_id = isset($widget_id) ? $widget_id : 'widget-' . uniqid(); + $toplytics_args = array( 'widget_id' => $widget_id . '-inner', 'period' => $period, @@ -209,8 +222,8 @@ public function update($new_instance, $old_instance) $instance['loadViaJS'] = isset($new_instance['loadViaJS']) ? 1 : 0; // If the category is set, add hook for refreshing the Toplytics posts for the categories. - if ( $instance['category'] != $old_instance['category'] ) { - add_action( 'update_option_widget_toplytics-widget', array( $this, 'update_additional_posts_data' ), 10, 3 ); + if (isset($instance['category']) && isset($old_instance['category']) && $instance['category'] != $old_instance['category']) { + add_action('update_option_widget_toplytics-widget', array($this, 'update_additional_posts_data'), 10, 3); } return $instance; diff --git a/src/composer.json b/src/composer.json old mode 100755 new mode 100644 index fd478c3e..b0c6fc3a --- a/src/composer.json +++ b/src/composer.json @@ -15,15 +15,17 @@ } ], "require": { - "php": "~7.0", - "google/apiclient": "^2.10" + "php": "^7.4", + "google/apiclient": "^2.12", + "google/apiclient-services": "^0.311.0" }, "scripts": { "pre-autoload-dump": "Google\\Task\\Composer::cleanup" }, "extra": { "google/apiclient-services": [ - "Analytics" + "Analytics", + "AnalyticsData" ] }, "autoload": { diff --git a/src/composer.lock b/src/composer.lock index 2e85cad0..b94d2585 100644 --- a/src/composer.lock +++ b/src/composer.lock @@ -4,34 +4,35 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "5bb48cfc408710b4be0eb405071842c4", + "content-hash": "d9b80235bd7c3c6d8aea770842cc07b8", "packages": [ { "name": "firebase/php-jwt", - "version": "v6.2.0", + "version": "v6.8.1", "source": { "type": "git", "url": "https://github.com/firebase/php-jwt.git", - "reference": "d28e6df83830252650da4623c78aaaf98fb385f3" + "reference": "5dbc8959427416b8ee09a100d7a8588c00fb2e26" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/firebase/php-jwt/zipball/d28e6df83830252650da4623c78aaaf98fb385f3", - "reference": "d28e6df83830252650da4623c78aaaf98fb385f3", + "url": "https://api.github.com/repos/firebase/php-jwt/zipball/5dbc8959427416b8ee09a100d7a8588c00fb2e26", + "reference": "5dbc8959427416b8ee09a100d7a8588c00fb2e26", "shasum": "" }, "require": { - "php": "^7.1||^8.0" + "php": "^7.4||^8.0" }, "require-dev": { "guzzlehttp/guzzle": "^6.5||^7.4", - "phpspec/prophecy-phpunit": "^1.1", - "phpunit/phpunit": "^7.5||^9.5", + "phpspec/prophecy-phpunit": "^2.0", + "phpunit/phpunit": "^9.5", "psr/cache": "^1.0||^2.0", "psr/http-client": "^1.0", "psr/http-factory": "^1.0" }, "suggest": { + "ext-sodium": "Support EdDSA (Ed25519) signatures", "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present" }, "type": "library", @@ -64,44 +65,43 @@ ], "support": { "issues": "https://github.com/firebase/php-jwt/issues", - "source": "https://github.com/firebase/php-jwt/tree/v6.2.0" + "source": "https://github.com/firebase/php-jwt/tree/v6.8.1" }, - "time": "2022-05-13T20:54:50+00:00" + "time": "2023-07-14T18:33:00+00:00" }, { "name": "google/apiclient", - "version": "v2.12.6", + "version": "v2.15.1", "source": { "type": "git", "url": "https://github.com/googleapis/google-api-php-client.git", - "reference": "f92aa126903a9e2da5bd41a280d9633cb249e79e" + "reference": "7a95ed29e4b6c6859d2d22300c5455a92e2622ad" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/googleapis/google-api-php-client/zipball/f92aa126903a9e2da5bd41a280d9633cb249e79e", - "reference": "f92aa126903a9e2da5bd41a280d9633cb249e79e", + "url": "https://api.github.com/repos/googleapis/google-api-php-client/zipball/7a95ed29e4b6c6859d2d22300c5455a92e2622ad", + "reference": "7a95ed29e4b6c6859d2d22300c5455a92e2622ad", "shasum": "" }, "require": { - "firebase/php-jwt": "~2.0||~3.0||~4.0||~5.0||~6.0", + "firebase/php-jwt": "~6.0", "google/apiclient-services": "~0.200", - "google/auth": "^1.10", - "guzzlehttp/guzzle": "~5.3.3||~6.0||~7.0", + "google/auth": "^1.28", + "guzzlehttp/guzzle": "~6.5||~7.0", "guzzlehttp/psr7": "^1.8.4||^2.2.1", - "monolog/monolog": "^1.17||^2.0||^3.0", - "php": "^5.6|^7.0|^8.0", - "phpseclib/phpseclib": "~2.0||^3.0.2" + "monolog/monolog": "^2.9||^3.0", + "php": "^7.4|^8.0", + "phpseclib/phpseclib": "^3.0.19" }, "require-dev": { - "cache/filesystem-adapter": "^0.3.2|^1.1", + "cache/filesystem-adapter": "^1.1", "composer/composer": "^1.10.22", "phpcompatibility/php-compatibility": "^9.2", - "phpspec/prophecy-phpunit": "^1.1||^2.0", - "phpunit/phpunit": "^5.7.21 || ^6.0 || ^7.0 || ^8.0 || ^9.0", + "phpspec/prophecy-phpunit": "^2.0", + "phpunit/phpunit": "^9.5", "squizlabs/php_codesniffer": "^3.0", "symfony/css-selector": "~2.1", - "symfony/dom-crawler": "~2.1", - "yoast/phpunit-polyfills": "^1.0" + "symfony/dom-crawler": "~2.1" }, "suggest": { "cache/filesystem-adapter": "For caching certs and tokens (using Google\\Client::setCache)" @@ -134,26 +134,26 @@ ], "support": { "issues": "https://github.com/googleapis/google-api-php-client/issues", - "source": "https://github.com/googleapis/google-api-php-client/tree/v2.12.6" + "source": "https://github.com/googleapis/google-api-php-client/tree/v2.15.1" }, - "time": "2022-06-06T20:00:19+00:00" + "time": "2023-09-13T21:46:39+00:00" }, { "name": "google/apiclient-services", - "version": "v0.252.0", + "version": "v0.311.1", "source": { "type": "git", "url": "https://github.com/googleapis/google-api-php-client-services.git", - "reference": "9941c959f6a1f781e49019b78f453d54554dff73" + "reference": "e8816f6708fac9d78ab59ef27a61a08d0af84d1e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/9941c959f6a1f781e49019b78f453d54554dff73", - "reference": "9941c959f6a1f781e49019b78f453d54554dff73", + "url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/e8816f6708fac9d78ab59ef27a61a08d0af84d1e", + "reference": "e8816f6708fac9d78ab59ef27a61a08d0af84d1e", "shasum": "" }, "require": { - "php": ">=5.6" + "php": "^7.4||^8.0" }, "require-dev": { "phpunit/phpunit": "^5.7||^8.5.13" @@ -178,38 +178,38 @@ ], "support": { "issues": "https://github.com/googleapis/google-api-php-client-services/issues", - "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.252.0" + "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.311.1" }, - "time": "2022-06-06T01:20:11+00:00" + "time": "2023-08-06T00:56:12+00:00" }, { "name": "google/auth", - "version": "v1.21.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/googleapis/google-auth-library-php.git", - "reference": "73392bad2eb6852eea9084b6bbdec752515cb849" + "reference": "6028b072aa444d7edecbed603431322026704627" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/googleapis/google-auth-library-php/zipball/73392bad2eb6852eea9084b6bbdec752515cb849", - "reference": "73392bad2eb6852eea9084b6bbdec752515cb849", + "url": "https://api.github.com/repos/googleapis/google-auth-library-php/zipball/6028b072aa444d7edecbed603431322026704627", + "reference": "6028b072aa444d7edecbed603431322026704627", "shasum": "" }, "require": { - "firebase/php-jwt": "^5.5||^6.0", + "firebase/php-jwt": "^6.0", "guzzlehttp/guzzle": "^6.2.1|^7.0", - "guzzlehttp/psr7": "^1.7|^2.0", - "php": "^7.1||^8.0", - "psr/cache": "^1.0|^2.0|^3.0", - "psr/http-message": "^1.0" + "guzzlehttp/psr7": "^2.4.5", + "php": "^7.4||^8.0", + "psr/cache": "^1.0||^2.0||^3.0", + "psr/http-message": "^1.1||^2.0" }, "require-dev": { - "guzzlehttp/promises": "0.1.1|^1.3", - "kelvinmo/simplejwt": "^0.2.5|^0.5.1", - "phpseclib/phpseclib": "^2.0.31", - "phpspec/prophecy-phpunit": "^1.1", - "phpunit/phpunit": "^7.5||^8.5", + "guzzlehttp/promises": "^2.0", + "kelvinmo/simplejwt": "0.7.1", + "phpseclib/phpseclib": "^3.0", + "phpspec/prophecy-phpunit": "^2.0", + "phpunit/phpunit": "^9.0.0", "sebastian/comparator": ">=1.2.3", "squizlabs/php_codesniffer": "^3.5" }, @@ -236,28 +236,28 @@ "support": { "docs": "https://googleapis.github.io/google-auth-library-php/main/", "issues": "https://github.com/googleapis/google-auth-library-php/issues", - "source": "https://github.com/googleapis/google-auth-library-php/tree/v1.21.0" + "source": "https://github.com/googleapis/google-auth-library-php/tree/v1.30.0" }, - "time": "2022-04-13T20:35:52+00:00" + "time": "2023-09-07T19:13:44+00:00" }, { "name": "guzzlehttp/guzzle", - "version": "7.4.4", + "version": "7.8.0", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "e3ff079b22820c2029d4c2a87796b6a0b8716ad8" + "reference": "1110f66a6530a40fe7aea0378fe608ee2b2248f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/e3ff079b22820c2029d4c2a87796b6a0b8716ad8", - "reference": "e3ff079b22820c2029d4c2a87796b6a0b8716ad8", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/1110f66a6530a40fe7aea0378fe608ee2b2248f9", + "reference": "1110f66a6530a40fe7aea0378fe608ee2b2248f9", "shasum": "" }, "require": { "ext-json": "*", - "guzzlehttp/promises": "^1.5", - "guzzlehttp/psr7": "^1.8.3 || ^2.1", + "guzzlehttp/promises": "^1.5.3 || ^2.0.1", + "guzzlehttp/psr7": "^1.9.1 || ^2.5.1", "php": "^7.2.5 || ^8.0", "psr/http-client": "^1.0", "symfony/deprecation-contracts": "^2.2 || ^3.0" @@ -266,10 +266,11 @@ "psr/http-client-implementation": "1.0" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.4.1", + "bamarni/composer-bin-plugin": "^1.8.1", "ext-curl": "*", - "php-http/client-integration-tests": "^3.0", - "phpunit/phpunit": "^8.5.5 || ^9.3.5", + "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999", + "php-http/message-factory": "^1.1", + "phpunit/phpunit": "^8.5.29 || ^9.5.23", "psr/log": "^1.1 || ^2.0 || ^3.0" }, "suggest": { @@ -279,8 +280,9 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "7.4-dev" + "bamarni-bin": { + "bin-links": true, + "forward-command": false } }, "autoload": { @@ -346,7 +348,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.4.4" + "source": "https://github.com/guzzle/guzzle/tree/7.8.0" }, "funding": [ { @@ -362,38 +364,37 @@ "type": "tidelift" } ], - "time": "2022-06-09T21:39:15+00:00" + "time": "2023-08-27T10:20:53+00:00" }, { "name": "guzzlehttp/promises", - "version": "1.5.1", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "fe752aedc9fd8fcca3fe7ad05d419d32998a06da" + "reference": "111166291a0f8130081195ac4556a5587d7f1b5d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/fe752aedc9fd8fcca3fe7ad05d419d32998a06da", - "reference": "fe752aedc9fd8fcca3fe7ad05d419d32998a06da", + "url": "https://api.github.com/repos/guzzle/promises/zipball/111166291a0f8130081195ac4556a5587d7f1b5d", + "reference": "111166291a0f8130081195ac4556a5587d7f1b5d", "shasum": "" }, "require": { - "php": ">=5.5" + "php": "^7.2.5 || ^8.0" }, "require-dev": { - "symfony/phpunit-bridge": "^4.4 || ^5.1" + "bamarni/composer-bin-plugin": "^1.8.1", + "phpunit/phpunit": "^8.5.29 || ^9.5.23" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "1.5-dev" + "bamarni-bin": { + "bin-links": true, + "forward-command": false } }, "autoload": { - "files": [ - "src/functions_include.php" - ], "psr-4": { "GuzzleHttp\\Promise\\": "src/" } @@ -430,7 +431,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/1.5.1" + "source": "https://github.com/guzzle/promises/tree/2.0.1" }, "funding": [ { @@ -446,20 +447,20 @@ "type": "tidelift" } ], - "time": "2021-10-22T20:56:57+00:00" + "time": "2023-08-03T15:11:55+00:00" }, { "name": "guzzlehttp/psr7", - "version": "2.5.0", + "version": "2.6.1", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "b635f279edd83fc275f822a1188157ffea568ff6" + "reference": "be45764272e8873c72dbe3d2edcfdfcc3bc9f727" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/b635f279edd83fc275f822a1188157ffea568ff6", - "reference": "b635f279edd83fc275f822a1188157ffea568ff6", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/be45764272e8873c72dbe3d2edcfdfcc3bc9f727", + "reference": "be45764272e8873c72dbe3d2edcfdfcc3bc9f727", "shasum": "" }, "require": { @@ -546,7 +547,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.5.0" + "source": "https://github.com/guzzle/psr7/tree/2.6.1" }, "funding": [ { @@ -562,20 +563,20 @@ "type": "tidelift" } ], - "time": "2023-04-17T16:11:26+00:00" + "time": "2023-08-27T10:13:57+00:00" }, { "name": "monolog/monolog", - "version": "2.7.0", + "version": "2.9.1", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "5579edf28aee1190a798bfa5be8bc16c563bd524" + "reference": "f259e2b15fb95494c83f52d3caad003bbf5ffaa1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/5579edf28aee1190a798bfa5be8bc16c563bd524", - "reference": "5579edf28aee1190a798bfa5be8bc16c563bd524", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/f259e2b15fb95494c83f52d3caad003bbf5ffaa1", + "reference": "f259e2b15fb95494c83f52d3caad003bbf5ffaa1", "shasum": "" }, "require": { @@ -590,16 +591,15 @@ "doctrine/couchdb": "~1.0@dev", "elasticsearch/elasticsearch": "^7 || ^8", "ext-json": "*", - "graylog2/gelf-php": "^1.4.2", + "graylog2/gelf-php": "^1.4.2 || ^2@dev", "guzzlehttp/guzzle": "^7.4", "guzzlehttp/psr7": "^2.2", "mongodb/mongodb": "^1.8", "php-amqplib/php-amqplib": "~2.4 || ^3", - "php-console/php-console": "^3.1.3", "phpspec/prophecy": "^1.15", "phpstan/phpstan": "^0.12.91", "phpunit/phpunit": "^8.5.14", - "predis/predis": "^1.1", + "predis/predis": "^1.1 || ^2.0", "rollbar/rollbar": "^1.3 || ^2 || ^3", "ruflin/elastica": "^7", "swiftmailer/swiftmailer": "^5.3|^6.0", @@ -619,7 +619,6 @@ "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)", "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", - "php-console/php-console": "Allow sending log messages to Google Chrome", "rollbar/rollbar": "Allow sending log messages to Rollbar", "ruflin/elastica": "Allow sending log messages to an Elastic Search server" }, @@ -654,7 +653,7 @@ ], "support": { "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/2.7.0" + "source": "https://github.com/Seldaek/monolog/tree/2.9.1" }, "funding": [ { @@ -666,7 +665,7 @@ "type": "tidelift" } ], - "time": "2022-06-09T08:59:12+00:00" + "time": "2023-02-06T13:44:46+00:00" }, { "name": "paragonie/constant_time_encoding", @@ -787,16 +786,16 @@ }, { "name": "phpseclib/phpseclib", - "version": "3.0.19", + "version": "3.0.23", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "cc181005cf548bfd8a4896383bb825d859259f95" + "reference": "866cc78fbd82462ffd880e3f65692afe928bed50" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/cc181005cf548bfd8a4896383bb825d859259f95", - "reference": "cc181005cf548bfd8a4896383bb825d859259f95", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/866cc78fbd82462ffd880e3f65692afe928bed50", + "reference": "866cc78fbd82462ffd880e3f65692afe928bed50", "shasum": "" }, "require": { @@ -877,7 +876,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/3.0.19" + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.23" }, "funding": [ { @@ -893,7 +892,7 @@ "type": "tidelift" } ], - "time": "2023-03-05T17:13:09+00:00" + "time": "2023-09-18T17:22:01+00:00" }, { "name": "psr/cache", @@ -946,21 +945,21 @@ }, { "name": "psr/http-client", - "version": "1.0.1", + "version": "1.0.2", "source": { "type": "git", "url": "https://github.com/php-fig/http-client.git", - "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621" + "reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", - "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/0955afe48220520692d2d09f7ab7e0f93ffd6a31", + "reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31", "shasum": "" }, "require": { "php": "^7.0 || ^8.0", - "psr/http-message": "^1.0" + "psr/http-message": "^1.0 || ^2.0" }, "type": "library", "extra": { @@ -980,7 +979,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common interface for HTTP clients", @@ -992,9 +991,9 @@ "psr-18" ], "support": { - "source": "https://github.com/php-fig/http-client/tree/master" + "source": "https://github.com/php-fig/http-client/tree/1.0.2" }, - "time": "2020-06-29T06:28:15+00:00" + "time": "2023-04-10T20:12:12+00:00" }, { "name": "psr/http-factory", @@ -1053,16 +1052,16 @@ }, { "name": "psr/http-message", - "version": "1.1", + "version": "2.0", "source": { "type": "git", "url": "https://github.com/php-fig/http-message.git", - "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba" + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/cb6ce4845ce34a8ad9e68117c10ee90a29919eba", - "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", "shasum": "" }, "require": { @@ -1071,7 +1070,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -1086,7 +1085,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common interface for HTTP messages", @@ -1100,9 +1099,9 @@ "response" ], "support": { - "source": "https://github.com/php-fig/http-message/tree/1.1" + "source": "https://github.com/php-fig/http-message/tree/2.0" }, - "time": "2023-04-04T09:50:52+00:00" + "time": "2023-04-04T09:54:51+00:00" }, { "name": "psr/log", @@ -1200,7 +1199,7 @@ }, { "name": "symfony/deprecation-contracts", - "version": "v2.5.1", + "version": "v2.5.2", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", @@ -1247,7 +1246,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.1" + "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.2" }, "funding": [ { @@ -1273,8 +1272,8 @@ "prefer-stable": true, "prefer-lowest": false, "platform": { - "php": "~7.0" + "php": "^7.4" }, "platform-dev": [], - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } diff --git a/src/languages/toplytics-ro_RO.po b/src/languages/toplytics-ro_RO.po old mode 100755 new mode 100644 index 9868942f..c12871d7 --- a/src/languages/toplytics-ro_RO.po +++ b/src/languages/toplytics-ro_RO.po @@ -444,8 +444,8 @@ msgstr "Autorizare Cont Google" #: resources/views/backend/authorization.blade.php:20 #: resources/views/backend/tabs/publicConnect.blade.php:12 -msgid "Public Authorization" -msgstr "Autorizare Publică" +msgid "Quick Connect" +msgstr "Conectare rapidă" #: resources/views/backend/authorization.blade.php:26 msgid "Private Authorization (Advanced)" diff --git a/src/resources/views/backend/authorization.php b/src/resources/views/backend/authorization.php old mode 100755 new mode 100644 index e9a6ca05..6672672f --- a/src/resources/views/backend/authorization.php +++ b/src/resources/views/backend/authorization.php @@ -28,14 +28,14 @@ - + - + diff --git a/src/resources/views/backend/settings.php b/src/resources/views/backend/settings.php index 3b4d86dc..24045e11 100755 --- a/src/resources/views/backend/settings.php +++ b/src/resources/views/backend/settings.php @@ -24,7 +24,7 @@