�PNG  IHDR22?�� pHYs  �� OiCCPPhotoshop ICC profilexڝSgTS�=���BK���KoR RB���&*! J�!��Q�EEȠ�����Q, � ��!���������{�kּ������>���� �H3Q5� �B�������.@� $p�d!s�#�~<<+"��x� �M��0���B�\���t�8K�@z�B�@F���&S�`�cb�P-`'������{[�!�� e�Dh;��V�EX0fK�9�-0IWfH���� � 0Q��){`�##x��F�W<�+��*x��<�$9E�[-qWW.(�I+6aa�@.�y�2�4���������x����6��_-��"bb���ϫp@�t~��,/��;�m��%�h^ �u��f�@����W�p�~<�5�j>{�-�]c�K'Xt����o��(�h���w��?�G�%�fI�q^D$.Tʳ?�D��*�A��,���� �`6�B$��BB d�r`)��B(�Ͱ*`/�@4�Qh��p.�U�=p�a��(�� A�a!ڈb�X#����!�H�$ ɈQ"K�5H1R�T UH�=r9�\F��;�2����G1���Q=� �C��7�F� �dt1�����r�=�6��Ыhڏ>C�0��3�l0.��B�8, �c˱"� ���V����cϱw�E� 6wB aAHXLXN�H� $4� 7 �Q�'"��K�&���b21�XH,#��/{�C�7$�C2'��I��T��F�nR#�,��4H#���dk�9�, +ȅ����3��!�[ �b@q��S�(R�jJ��4�e�2AU��Rݨ�T5�ZB���R�Q��4u�9̓IK�����hh�i��t�ݕN��W���G���w ��Ljg(�gw��L�Ӌ�T071���oUX*�*|�� �J�&�*/T����ު U�U�T��^S}�FU3S� Ԗ�U��P�SSg�;���g�oT?�~Y��Y�L�OC�Q��_�� c�x,!k ��u�5�&���|v*�����=���9C3J3W�R�f?�q��tN �(���~���)�)�4L�1e\k����X�H�Q�G�6������E�Y��A�J'\'Gg����S�Sݧ �M=:��.�k���Dw�n��^��Lo��y���}/�T�m���G X� $� �<�5qo</���QC]�@C�a�a�ᄑ��<��F�F�i�\�$�m�mƣ&&!&KM�M�RM��)�;L;L���͢�֙5�=1�2��כ߷`ZxZ,����eI��Z�Yn�Z9Y�XUZ]�F���%ֻ�����N�N���gð�ɶ�����ۮ�m�}agbg�Ů��}�}��= ���Z~s�r:V:ޚΜ�?}����/gX���3��)�i�S��Ggg�s�󈋉K��.�>.���Ƚ�Jt�q]�z���������ۯ�6�i�ܟ�4�)�Y3s���C�Q��? ��0k߬~OCO�g��#/c/�W�װ��w��a�>�>r��>�<7�2�Y_�7��ȷ�O�o�_��C#�d�z����%g��A�[��z|!��?:�e����A���AA�������!h�쐭!��Α�i�P~���a�a��~ '���W�?�p�X�1�5w��Cs�D�D�Dޛg1O9�-J5*>�.j<�7�4�?�.fY��X�XIlK9.*�6nl������� �{�/�]py�����.,:�@L�N8��A*��%�w%� y��g"/�6ш�C\*N�H*Mz�쑼5y$�3�,幄'���L Lݛ:��v m2=:�1����qB�!M��g�g�fvˬe����n��/��k���Y- �B��TZ(�*�geWf�͉�9���+��̳�ې7�����ᒶ��KW-X潬j9�������(�x��oʿ�ܔ���Ĺd�f�f���-�[����n �ڴ �V����E�/��(ۻ��C���<��e����;?T�T�T�T6��ݵa��n��{��4���[���>ɾ�UUM�f�e�I���?�������m]�Nmq����#�׹���=TR��+�G�����w- 6 U����#pDy��� �� :�v�{���vg/jB��F�S��[b[�O�>����z�G��499�?r����C�d�&����ˮ/~�����јѡ�򗓿m|������������x31^�V���w�w��O�| (�h���SЧ��������c3-� cHRMz%������u0�`:�o�_�F5IDATx��ytUս�?�;���fN$$��@B�!�k��� -*�gE���j�O�kQ�ʠ`U�B_ �AÐ0%�Ȕ�@r3ޛ;߳��$�@��v����^�s����������$��ߢ !�W��5�̱'-٘������4�>�Rƫ$�G��0U�H}�_ _� #��k�MJ/=�9Du *ڲ�k�PQ;0��j|�*�$�^컂脛y���>�z×� B��� ��(�:$�ʔ_�6��C!B����MVx��a��ζyY����j��ƋY2�9�F�{r��r�딟F��Q��hY6��� x��[l��RC��������nt@��;P��3��� F�w��7��:�P���ɋ'���mj���Bƪ�$�Q�L��y��߷g��\���z����v5�p�v$�v櫻�`6~K �Y�X����,�:��"�o�e0II"(��,������l_�C���/4�+f�E�!q��:����u����c��樼.UE�@� �]K�W���$-�h]�JG���Dz)�`��.�A/ ���mᏣc�3jK� �!�>���$�Q�!�_�? \�C2(E �M$Z I{�U���s�ǣ���=��@Բe ޻��W�����@ �w����}�9v,)��.}*|"�s��di���,���G�]W�AC�������|<����[��ߕ������K�*�G nߴ!��‹��J�!��6(L�a)��Am��������;adf��:�xm��nh�;֦I��(���o�C~ډa?�=��s����h��E������xp����)���_���t��W�����´;8���`dz=(��@@�+,�;�`�fhl��XȌ�3,uI�~z(J����� �ZX�A����H'�À�㜦�82|��a�n�z2��I���� ���EY�h�ε<�0�q�{��C��v�˅��?"@��χ�x�WS+��N�~�KQ�J�8ل�� _.W��� !TU{�����,��"�� �;�������HI S� ��))�o�1�H�D� ���� (� ;����"Ҕ��,���� �F=���O��&�Ph>�`���y��߲ &S��P�<��'��1s�1cĂ�N����2)����@�u��tv��<�+�-&�����h��[!FSG���' � z z0��<����8d&�����E0�,��<��"!P�b4��� �{S�����X����.�囤���T��hEF��X�q0"-<����h���]�Py*����F⩍��@v�˂�Y08�� .q��a��s����(!<̫1�3�L�H��7sYW�`��qtu�\7��?�@�Y�� %Ka�x�GZ�*W�P��y�����N0r9��Z�c�%���q,��k�����!!,��>���IB��� �x1�Xu�Y���v-���ֺ��N������JP��a�2`�e5��w��u;�6�i���̃��(K���ťa��(l51��JL��O'%���]���ٖ뿉!��{*�p+f ���i8��D�ȑ���ܩ�M��V��ӟz��x�7Z�1i}�^͜���6e����x��)u�d�ˏ�V�eG�\�X1�����=n�U'�~Y����L�\,�(d!x ,�:�TW8� M`r���@��r+v�Q0��>^;˴�VbF��('����� �*O��i��j�Ӆ����^�S3&� ���{������.ی�� N;��NU%d0�Ce\r"�C�b��&t7N�7��� �ȪD�[%l�۪�$��'m?�A9tI�9>��NVL ��� 6v~M�����ъ�B���0����9$&=ώm��W�0���L���&��E���f�f��'+�9��hv��7,���M��6�D�&�^� �����8 D֮�����o��k^z��O��hP�8q�5d*��YVq3�{��������#LX4�?��jP=3�~�؅c�ݰ�̱�ұ��8̲��2�G�����j��έ�9��w7���U�X�w�85C��?!I&���o&����L���I#�^�eV�,�^t5�k� �xs˛\��U�8��."���{���ǵ�l4��ݼ�;��r"���G�/~���gJV�N糦��ZZ^k+NN�D��I$�=OE�z����|*�*{��%k���G��>�`9��b;�s���8,�qs��c��.b��q�%�>r��n�R�Ƨ�%�,�A��le#�8���}; 21�0�b�&�QX�f���q�00����$>�h�N�'�a3��A���/�r ��L5�8�GԲ'�����w;��c#�q1���h$*��V^�k��QĽ�b:i������� ����H F#�_���,��]g����Ը����`RUU���� ��"�qD���>-��ϤI�~��3�̴�����NZ[[555�eeek7�m����YF#[��Đ��R��i��L�H�r ��@��J-�Pŝ��_|�-��6y��ks�V�U~��6���w.����(��0A� 4��f��� /���C�xŊ�ٳ����z=6�����rg���mKo��o�/����a�g���?'9%9��P��斓��~���L{�� �H��{AW��B��$����v�1b�&Mb�ر��ر#�0`�`xMBp! )Z�Nmo�mZ�g�}�eذaWTVV ���'99��C5��&�&+5�bT>|8��PUUETT����&���t��~TE%��'������b�tEGG;RSS�S�N�v��ѯ��t����u1@�ޚ"f��͈���r'L�Ph��m��ƌ�74o��`�x�q�P���NRSS�X,�����l&&&��MFFA!-��`��ҷ�n��Yuu�����x<I�LB%����KԒ50�!�3�bz�����ʸKL���;---�l6[��`��������Ȏ;�����egg4��!D�T��jWujyZ��������K����%����p�^���X,6��sV=�ܖ����6�3�X ���4ҿ��A2�&����_k�;d�� �VfOIEND�B`�
Warning: session_start(): Session cannot be started after headers have already been sent in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 124

Warning: Cannot modify header information - headers already sent by (output started at /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php:1) in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 130

Warning: Cannot modify header information - headers already sent by (output started at /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php:1) in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 131

Warning: Cannot modify header information - headers already sent by (output started at /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php:1) in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 132

Warning: Cannot modify header information - headers already sent by (output started at /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php:1) in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 133

Warning: Cannot modify header information - headers already sent by (output started at /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php:1) in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 134

Warning: Cannot modify header information - headers already sent by (output started at /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php:1) in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 135

Warning: Cannot modify header information - headers already sent by (output started at /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php:1) in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 547

Warning: Cannot modify header information - headers already sent by (output started at /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php:1) in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 548

Warning: Cannot modify header information - headers already sent by (output started at /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php:1) in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 549

Warning: Cannot modify header information - headers already sent by (output started at /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php:1) in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 550

Warning: Cannot modify header information - headers already sent by (output started at /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php:1) in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 551
blog_id ); $store_urls[] = home_url(); restore_current_blog(); } } else { $store_urls[] = home_url(); } $base_url = trailingslashit( $clarity_server_url ); $plugin_installed_endpoint = $base_url . 'woocommerce/plugin-installed'; $upsell_ingest_endpoint = $base_url . 'woocommerce/upsell-ingest'; foreach ( $store_urls as $store_url ) { $request_args = array( 'blocking' => false, 'timeout' => 3, 'headers' => array( 'Content-Type' => 'application/json' ), 'body' => wp_json_encode( array( 'storeUrl' => $store_url ) ), ); // plugin-installed: BA server creates AdvertiserMetadata for this store. // Even with blocking=false, wp_remote_post() can fail immediately (e.g., invalid URL, transport error). $response = wp_remote_post( $plugin_installed_endpoint, $request_args ); if ( is_wp_error( $response ) ) { brandagent_log( 'BrandAgent Lifecycle: plugin-installed call failed; retrying once', array( 'endpoint' => $plugin_installed_endpoint, 'error' => $response->get_error_message(), ) ); $response = wp_remote_post( $plugin_installed_endpoint, $request_args ); if ( is_wp_error( $response ) ) { brandagent_log( 'BrandAgent Lifecycle: plugin-installed call failed after retry', array( 'endpoint' => $plugin_installed_endpoint, 'error' => $response->get_error_message(), ) ); } } // upsell-ingest: pre-index products so they are ready before the merchant reaches publish. $response = wp_remote_post( $upsell_ingest_endpoint, $request_args ); if ( is_wp_error( $response ) ) { brandagent_log( 'BrandAgent Lifecycle: upsell-ingest call failed; retrying once', array( 'endpoint' => $upsell_ingest_endpoint, 'error' => $response->get_error_message(), ) ); $response = wp_remote_post( $upsell_ingest_endpoint, $request_args ); if ( is_wp_error( $response ) ) { brandagent_log( 'BrandAgent Lifecycle: upsell-ingest call failed after retry', array( 'endpoint' => $upsell_ingest_endpoint, 'error' => $response->get_error_message(), ) ); } } } } // Don't do redirects when multiple plugins are bulk activated if ( (isset($_REQUEST['action']) && 'activate-selected' === $_REQUEST['action']) && (isset($_POST['checked']) && count($_POST['checked']) > 1) ) { return; } add_option('clarity_activation_redirect', wp_get_current_user()->ID); } /** * Redirects the user after plugin activation */ function clarity_activation_redirect() { // Make sure it is the user that activated the plugin if (is_user_logged_in() && intval(get_option('clarity_activation_redirect', false)) === wp_get_current_user()->ID) { // Make sure we don't redirect again delete_option('clarity_activation_redirect'); wp_safe_redirect(admin_url('admin.php?page=microsoft-clarity')); exit; } } /** * Runs when Clarity Plugin is deactivated. */ register_deactivation_hook(__FILE__, 'clarity_on_deactivation'); function clarity_on_deactivation($network_wide) { clrt_update_clarity_options('deactivate', $network_wide); flush_rewrite_rules(); } /** * Runs when Clarity Plugin is uninstalled. */ register_uninstall_hook(__FILE__, 'clarity_on_uninstall'); function clarity_on_uninstall() { // Uninstall hook doesn't pass $network_wide flag. // Set it to true to delete options for all the sites in a multisite setup (in a single site setup, the flag is irrelevant). clrt_update_clarity_options('uninstall', true); } /** * Updates clarity options based on the plugin's action and WordPress installation type. * * @since 0.10.1 * * @param string $action activate, deactivate or uninstall. * @param bool $network_wide In case of a multisite installation, should the action be performed on all the sites or not. */ function clrt_update_clarity_options($action, $network_wide) { if (is_multisite() && $network_wide) { $sites = get_sites(); foreach ($sites as $site) { switch_to_blog($site->blog_id); clrt_update_clarity_options_handler($action, $network_wide); restore_current_blog(); } } else { clrt_update_clarity_options_handler($action, $network_wide); } } /** * @since 0.10.1 */ function clrt_update_clarity_options_handler($action, $network_wide) { switch ($action) { case 'activate': $id = get_option('clarity_wordpress_site_id'); if (! $id) { update_option('clarity_wordpress_site_id', wp_generate_uuid4()); } // Clear the cached version flag so a reinstall re-evaluates instead of inheriting a stale banner. delete_transient('clarity_is_latest_plugin_version'); // Initialize BAInjectFrontendScript with default value if ( get_option( 'BAInjectFrontendScript' ) === false ) { add_option( 'BAInjectFrontendScript', 'false' ); brandagent_log( 'BrandAgent Lifecycle: Initialized BAInjectFrontendScript option', array( 'value' => 'false' ) ); } // Resume all BrandAgent webhooks if ( class_exists( 'BrandAgent_Webhooks' ) ) { $resumed_count = BrandAgent_Webhooks::resume_all_brandagent_webhooks(); brandagent_log( 'BrandAgent Lifecycle: Plugin activated; resumed webhooks', array( 'resumed_count' => $resumed_count ) ); } else { brandagent_log( 'BrandAgent Lifecycle: Plugin activated; BrandAgent_Webhooks class not available for resume' ); } break; case 'deactivate': // Plugin activation/deactivation is handled differently in the database for site-level and network-wide activation. // Ensure a complete deactivation if the plugin was activated per site before network-wide activation. $plugin_name = plugin_basename(__FILE__); if ($network_wide && in_array($plugin_name, (array) get_option('active_plugins', array()), true)) { deactivate_plugins($plugin_name, true, false); } update_option('clarity_wordpress_site_id', ''); update_option('clarity_project_id', ''); clarity_flush_and_clear_collect_recurring(); // Pause all BrandAgent webhooks if ( class_exists( 'BrandAgent_Webhooks' ) ) { $paused_count = BrandAgent_Webhooks::pause_all_brandagent_webhooks(); brandagent_log( 'BrandAgent Lifecycle: Plugin deactivated; paused webhooks', array( 'paused_count' => $paused_count ) ); } else { brandagent_log( 'BrandAgent Lifecycle: Plugin deactivated; BrandAgent_Webhooks class not available for pause' ); } break; case 'uninstall': brandagent_log( 'BrandAgent Lifecycle: Plugin uninstall started' ); handle_brandagent_uninstall(); delete_option('clarity_wordpress_site_id'); delete_option('clarity_project_id'); delete_option( 'BAOauthSuccess' ); delete_option( 'BAInjectFrontendScript' ); delete_option( 'BAOauthRepairDone' ); delete_option( 'BAWebhooksCreated' ); delete_option( 'BAWebhooksBackfillDone' ); delete_option( 'clarity_ba_eligible_triggered' ); // Cleanup for the option used up to version 0.10.16. Should remove this after users migrate to 0.10.17+ where this option is no longer used. delete_option('clarity_collect_batch'); // Remove the cached banner flag so it can't linger and resurface on reinstall. delete_transient('clarity_is_latest_plugin_version'); delete_option('clarity_dismissed_update_version'); clarity_flush_and_clear_collect_recurring(); clarity_drop_collect_events_table(); // Delete all BrandAgent webhooks if ( class_exists( 'BrandAgent_Webhooks' ) ) { $deleted_count = BrandAgent_Webhooks::delete_all_brandagent_webhooks(); brandagent_log( 'BrandAgent Lifecycle: Plugin uninstall deleted webhooks', array( 'deleted_count' => $deleted_count ) ); } else { brandagent_log( 'BrandAgent Lifecycle: Plugin uninstall; BrandAgent_Webhooks class not available for deletion' ); } // Delete stored HMAC secret for this store if ( function_exists( 'brandagent_delete_hmac_secret' ) ) { brandagent_delete_hmac_secret(); } else { brandagent_log( 'BrandAgent Lifecycle: Plugin uninstall; HMAC delete helper not available' ); } brandagent_log( 'BrandAgent Lifecycle: Plugin uninstall completed' ); break; } } /** * Escapes the plugin id characters. */ function escape_value_for_script($value) { return htmlspecialchars($value, ENT_QUOTES, 'UTF-8'); } /** * Adds the script to run clarity. */ add_action('wp_head', 'clarity_add_script_to_header'); function clarity_add_script_to_header() { $clarity_project_id = get_option('clarity_project_id'); if (! empty($clarity_project_id)) { ?> for block themes, in the footer for classic * themes), so the import map is always registered first. That keeps the * WooCommerce Interactivity API (mini-cart, add-to-cart, product collections, * checkout) working in browsers that reject import maps registered after a * module load has started (Firefox, Chrome < 133, Android WebView). */ add_action('wp_enqueue_scripts', 'brand_agent_enqueue_frontend_module'); function brand_agent_enqueue_frontend_module() { // Only handled here on WordPress 6.5+; older versions use the inline fallback. if ( ! function_exists( 'wp_enqueue_script_module' ) ) { return; } if ( ! brand_agent_should_inject_frontend_script() ) { return; } wp_enqueue_script_module( 'brand-agent-frontend', BrandAgent_Config::get_frontend_injection_url(), array(), null ); } /** * Fallback loader for WordPress versions without the Script Modules API (< 6.5). * Those versions predate the block Interactivity API import map, so injecting the * module from an inline script is safe. Insertion is still deferred until the * document has parsed as a defensive measure. */ add_action('wp_head', 'brand_agent_add_script_to_header'); function brand_agent_add_script_to_header() { // WordPress 6.5+ is handled by the Script Modules API path above. if ( function_exists( 'wp_enqueue_script_module' ) ) { return; } if ( ! brand_agent_should_inject_frontend_script() ) { return; } $frontend_injection_url = BrandAgent_Config::get_frontend_injection_url(); ?> " . __('Clarity Dashboard') . ''; array_unshift($links, $clarity_link); return $links; } /** * Retrieving the currently installed plugin version */ function get_installed_plugin_version() { if (! function_exists('get_plugin_data')) { require_once(ABSPATH . 'wp-admin/includes/plugin.php'); } $plugin_data = get_plugin_data(plugin_dir_path(__FILE__) . 'clarity.php'); return $plugin_data['Version']; } /** * One-time migration: repair BAOauthSuccess if it was cleared by the * register_setting('general') bug (fixed in 0.10.23) while * BAInjectFrontendScript remained true and the HMAC secret is still present. */ add_action('admin_init', 'clarity_repair_oauth_status'); function clarity_repair_oauth_status() { if ( get_option('BAOauthRepairDone') ) { return; } if ( get_option('BAInjectFrontendScript') === 'true' && brandagent_get_hmac_secret() && get_option('BAOauthSuccess') != 1 ) { update_option('BAOauthSuccess', true); brandagent_log( 'BrandAgent OAuth Repair: Restored BAOauthSuccess from existing Brand Agent state' ); } update_option('BAOauthRepairDone', true); } /** * One-time migration: backfill BAWebhooksCreated for stores that already have * BrandAgent webhooks set up before this flag existed. Without this, a future * config/update would unnecessarily re-trigger complete-onboarding + * create_webhooks() for healthy stores. Stores that completed OAuth but never * got webhooks (the bug we're fixing) are intentionally left without the flag, * so the next config/update will recover them. */ add_action('admin_init', 'clarity_backfill_webhooks_created'); function clarity_backfill_webhooks_created() { if ( get_option('BAWebhooksBackfillDone') ) { return; } // Defer if WooCommerce isn't ready yet — without WC_Webhook, has_any_brandagent_webhook() // would return false for healthy stores and we'd mark the backfill done with the flag // unset, causing one unnecessary complete-onboarding round-trip on the next config/update. if ( ! class_exists('BrandAgent_Webhooks') || ! class_exists('WC_Webhook') ) { return; } if ( get_option('BAOauthSuccess') == 1 && get_option('BAInjectFrontendScript') === 'true' && BrandAgent_Webhooks::has_any_brandagent_webhook() ) { update_option('BAWebhooksCreated', true); } update_option('BAWebhooksBackfillDone', true); } /** * Refresh the cached "update available" flag used by the admin banner. * Gated on core's update_plugins->response (the same source the Update button * installs from), so the banner never offers an update that can't yet be installed. */ add_action('admin_init', 'check_if_installed_plugin_version_is_latest'); function check_if_installed_plugin_version_is_latest() { // Skip for ajax requests. if (wp_doing_ajax()) { return; } // Throttle the check to every 5 minutes. if (get_transient('clarity_is_latest_plugin_version') !== false) { return; } // Refresh core's update data (self-throttled internally) and read its verdict. wp_update_plugins(); $plugin_file = plugin_basename(__FILE__); $updates = get_site_transient('update_plugins'); $update_available = isset($updates->response[$plugin_file]->new_version); set_transient('clarity_is_latest_plugin_version', $update_available ? '0' : '1', 5 * 60); // 5 minutes cache } /** * Clear cached plugin-version status after this plugin is installed or updated. * This is needed to avoid showing a banner after update due to stale cache. */ add_action('upgrader_process_complete', 'clarity_invalidate_latest_version_transient_on_update', 10, 2); function clarity_invalidate_latest_version_transient_on_update($upgrader_object, $options) { if (! is_array($options) || ($options['type'] ?? '') !== 'plugin') { return; } $action = $options['action'] ?? ''; if ($action !== 'update' && $action !== 'install') { return; } // Bulk updates pass a 'plugins' array; single update/install passes a 'plugin' string. $affected_plugins = (array) ($options['plugins'] ?? array()); if (! empty($options['plugin'])) { $affected_plugins[] = $options['plugin']; } // On overwrite-install the affected plugin isn't always reported; clear anyway to be safe. if (! empty($affected_plugins) && ! in_array(plugin_basename(__FILE__), $affected_plugins, true)) { return; } delete_transient('clarity_is_latest_plugin_version'); } /** * Check if script should be injected on current page */ function should_inject_brand_agents_script() { if ( get_option( 'BAInjectFrontendScript', 'false' ) !== 'true' ) { return false; } // Don't inject on admin pages if ( is_admin() ) { return false; } // Don't inject on login/register pages if ( function_exists( 'is_login' ) && is_login() ) { return false; } // Don't inject on wp-login.php if ( $GLOBALS['pagenow'] === 'wp-login.php' ) { return false; } // Inject on all other pages return true; } /** * Brand Agent Proxy Endpoints * Rewrite rules and handlers for proxying requests from the frontend to the * BrandAgent backend server. HMAC helper functions are defined in * includes/brandagent-config.php (loaded first to be available during OAuth callback). */ /** * Register rewrite rules for Brand Agent proxy endpoints */ function brandagent_register_routes() { add_rewrite_rule( '^a/msba/(.*)', 'index.php?brandagent_api=1&brandagent_path=$matches[1]', 'top' ); } add_action( 'init', 'brandagent_register_routes' ); /** * Register query vars for Brand Agent endpoints */ function brandagent_register_query_vars( $vars ) { $vars[] = 'brandagent_api'; $vars[] = 'brandagent_path'; return $vars; } add_filter( 'query_vars', 'brandagent_register_query_vars' ); /** * Handle Brand Agent custom endpoint requests */ function brandagent_handle_custom_endpoint() { if ( intval( get_query_var( 'brandagent_api' ) ) === 1 ) { require_once plugin_dir_path( __FILE__ ) . 'includes/brandagent-endpoint.php'; exit; } } add_action( 'template_redirect', 'brandagent_handle_custom_endpoint' ); /** * Register Brand Agent REST API endpoints */ function brandagent_register_rest_api() { $rest_api = new BrandAgent_REST_API(); $rest_api->register_routes(); } add_action( 'rest_api_init', 'brandagent_register_rest_api' ); /** * Check for pending webhook deletion after WordPress is initialized * This handles the case where webhook deletion was requested but WooCommerce wasn't loaded yet * Uses 'init' hook with priority 20 to ensure WooCommerce is available */ add_action( 'init', 'brandagent_process_pending_webhook_deletion', 20 ); function brandagent_process_pending_webhook_deletion() { $pending = get_transient( 'brandagent_pending_webhook_deletion' ); if ( ! $pending ) { return; } // Check if WooCommerce is available if ( ! class_exists( 'WooCommerce' ) || ! class_exists( 'WC_Webhook' ) ) { brandagent_log( 'BrandAgent Webhooks: WooCommerce not available yet for pending webhook deletion' ); return; } // Delete the transient first to prevent multiple attempts delete_transient( 'brandagent_pending_webhook_deletion' ); if ( class_exists( 'BrandAgent_Webhooks' ) ) { $deleted_count = BrandAgent_Webhooks::delete_all_brandagent_webhooks(); brandagent_log( 'BrandAgent Webhooks: Deleted webhooks via pending deletion', array( 'deleted_count' => $deleted_count ) ); } else { brandagent_log( 'BrandAgent Webhooks: BrandAgent_Webhooks class not available for pending deletion' ); } } /** * Call Clarity dashboard uninstall endpoint to clean up BA server data * This function can be called during plugin uninstall to notify the backend */ function handle_brandagent_uninstall() { if ( get_option( 'BAOauthSuccess' ) != 1 ) { brandagent_log( 'BrandAgent Uninstall: Skipping backend uninstall because OAuth is not marked successful' ); return; } $site_url = home_url(); // HMAC-signed request through Clarity proxy $clarity_domain = BrandAgent_Config::get_clarity_server_url(); $uninstall_endpoint = $clarity_domain . '/woocommerce/uninstall'; brandagent_log( 'BrandAgent Uninstall: Calling backend uninstall endpoint', array( 'store_url' => $site_url, 'endpoint' => $uninstall_endpoint ) ); $response = brandagent_sign_outbound_request( $uninstall_endpoint, wp_json_encode( array( 'storeUrl' => $site_url ) ), 'POST', 15 ); // Log error if call fails, but continue with local cleanup if ( is_wp_error( $response ) ) { brandagent_log( 'BrandAgent Uninstall: Failed to call backend uninstall endpoint', array( 'error' => $response->get_error_message() ) ); return; } $status_code = wp_remote_retrieve_response_code( $response ); brandagent_log( 'BrandAgent Uninstall: Backend uninstall endpoint returned', array( 'status_code' => $status_code ) ); }