�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`� 0x0x
PHP 8.1.34
Preview: class-wc-admin-dashboard.php Size: 28.01 KB
/home2/astrociv/public_html/rudraraksham.com/wp-content/plugins/woocommerce/includes/admin/class-wc-admin-dashboard.php
<?php
/**
 * Admin Dashboard
 *
 * @package     WooCommerce\Admin
 * @version     2.1.0
 */

use Automattic\Jetpack\Constants;
use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Enums\OrderStatus;
use Automattic\WooCommerce\Enums\OrderInternalStatus;
use Automattic\WooCommerce\Utilities\OrderUtil;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

if ( ! class_exists( 'WC_Admin_Dashboard', false ) ) :

	/**
	 * WC_Admin_Dashboard Class.
	 */
	class WC_Admin_Dashboard {

		/**
		 * Hook in tabs.
		 */
		public function __construct() {
			// Only hook in admin parts if the user has admin access.
			if ( $this->should_display_widget() ) {
				// If on network admin, only load the widget that works in that context and skip the rest.
				if ( is_multisite() && is_network_admin() ) {
					add_action( 'wp_network_dashboard_setup', array( $this, 'register_network_order_widget' ) );
				} else {
					add_action( 'wp_dashboard_setup', array( $this, 'init' ) );
				}
			}
		}

		/**
		 * Init dashboard widgets.
		 */
		public function init() {
			// Reviews Widget.
			if ( current_user_can( 'publish_shop_orders' ) && post_type_supports( 'product', 'comments' ) ) {
				wp_add_dashboard_widget( 'woocommerce_dashboard_recent_reviews', __( 'WooCommerce Recent Reviews', 'woocommerce' ), array( $this, 'recent_reviews' ) );
			}
			wp_add_dashboard_widget( 'woocommerce_dashboard_status', __( 'WooCommerce Status', 'woocommerce' ), array( $this, 'status_widget' ) );

			// Network Order Widget.
			if ( is_multisite() && is_main_site() ) {
				$this->register_network_order_widget();
			}
		}

		/**
		 * Register the network order dashboard widget.
		 */
		public function register_network_order_widget() {
			wp_add_dashboard_widget( 'woocommerce_network_orders', __( 'WooCommerce Network Orders', 'woocommerce' ), array( $this, 'network_orders' ) );
		}

		/**
		 * Check to see if we should display the widget.
		 *
		 * @return bool
		 */
		private function should_display_widget() {
			if ( ! WC()->is_wc_admin_active() ) {
				return false;
			}

			$has_permission           = current_user_can( 'view_woocommerce_reports' ) || current_user_can( 'manage_woocommerce' ) || current_user_can( 'publish_shop_orders' );
			$task_completed_or_hidden = 'yes' === get_option( 'woocommerce_task_list_complete' ) || 'yes' === get_option( 'woocommerce_task_list_hidden' );
			return $task_completed_or_hidden && $has_permission;
		}

		/**
		 * Get top seller from DB.
		 *
		 * @return object
		 */
		private function get_top_seller() {
			global $wpdb;

			$hpos_enabled         = OrderUtil::custom_orders_table_usage_is_enabled();
			$orders_table         = OrderUtil::get_table_for_orders();
			$orders_column_id     = $hpos_enabled ? 'id' : 'ID';
			$orders_column_type   = $hpos_enabled ? 'type' : 'post_type';
			$orders_column_status = $hpos_enabled ? 'status' : 'post_status';
			$orders_column_date   = $hpos_enabled ? 'date_created_gmt' : 'post_date_gmt';

			$query           = array();
			$query['fields'] = "SELECT SUM( order_item_meta.meta_value ) as qty, order_item_meta_2.meta_value as product_id FROM {$orders_table} AS orders";
			$query['join']   = "INNER JOIN {$wpdb->prefix}woocommerce_order_items AS order_items ON orders.{$orders_column_id} = order_id ";
			$query['join']  .= "INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS order_item_meta ON order_items.order_item_id = order_item_meta.order_item_id ";
			$query['join']  .= "INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS order_item_meta_2 ON order_items.order_item_id = order_item_meta_2.order_item_id ";
			$query['where']  = "WHERE orders.{$orders_column_type} IN ( '" . implode( "','", wc_get_order_types( 'order-count' ) ) . "' ) ";

			/**
			 * Allows modifying the order statuses used in the top seller query inside the dashboard status widget.
			 *
			 * @since 2.2.0
			 *
			 * @param string[] $order_statuses Order statuses.
			 */
			$order_statuses  = apply_filters( 'woocommerce_reports_order_statuses', array( OrderStatus::COMPLETED, OrderStatus::PROCESSING, OrderStatus::ON_HOLD ) );
			$query['where'] .= "AND orders.{$orders_column_status} IN ( 'wc-" . implode( "','wc-", $order_statuses ) . "' ) ";

			$query['where']  .= "AND order_item_meta.meta_key = '_qty' ";
			$query['where']  .= "AND order_item_meta_2.meta_key = '_product_id' ";
			$query['where']  .= "AND orders.{$orders_column_date} >= '" . gmdate( 'Y-m-01', current_time( 'timestamp' ) ) . "' "; // phpcs:ignore WordPress.DateTime.CurrentTimeTimestamp.Requested
			$query['where']  .= "AND orders.{$orders_column_date} <= '" . gmdate( 'Y-m-d H:i:s', current_time( 'timestamp' ) ) . "' "; // phpcs:ignore WordPress.DateTime.CurrentTimeTimestamp.Requested
			$query['groupby'] = 'GROUP BY product_id';
			$query['orderby'] = 'ORDER BY qty DESC';
			$query['limits']  = 'LIMIT 1';

			/**
			 * Allows modification of the query to determine the top seller product in the dashboard status widget.
			 *
			 * @since 2.2.0
			 *
			 * @param array $query SQL query parts.
			 */
			$query = apply_filters( 'woocommerce_dashboard_status_widget_top_seller_query', $query );

			$sql = implode( ' ', $query );
			return $wpdb->get_row( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
		}

		/**
		 * Show status widget.
		 */
		public function status_widget() {
			$suffix  = Constants::is_true( 'SCRIPT_DEBUG' ) ? '' : '.min';
			$version = Constants::get_constant( 'WC_VERSION' );

			wp_enqueue_script( 'wc-status-widget', WC()->plugin_url() . '/assets/js/admin/wc-status-widget' . $suffix . '.js', array( 'jquery', 'wc-flot' ), $version, true );
			wp_enqueue_script( 'wc-status-widget-async', WC()->plugin_url() . '/assets/js/admin/wc-status-widget-async' . $suffix . '.js', array( 'jquery' ), $version, true );

			wp_localize_script(
				'wc-status-widget-async',
				'wc_status_widget_params',
				array(
					'ajax_url'      => admin_url( 'admin-ajax.php' ),
					'security'      => wp_create_nonce( 'wc-status-widget' ),
					'error_message' => esc_html__( 'Error loading widget', 'woocommerce' ),
				)
			);

			// Display loading placeholder.
			echo '<div id="wc-status-widget-loading" class="wc-status-widget-loading">';
			echo '<p>' . esc_html__( 'Loading status data...', 'woocommerce' ) . ' <span class="spinner is-active"></span></p>';
			echo '</div>';
			echo '<div id="wc-status-widget-content" style="display:none;"></div>';
		}

		/**
		 * Generate the actual status widget content.
		 * This contains the original content of the status_widget() method.
		 */
		public function status_widget_content() {
			//phpcs:ignore
			$is_wc_admin_disabled = apply_filters( 'woocommerce_admin_disabled', false ) || ! Features::is_enabled( 'analytics' );

			$status_widget_reports = array(
				'net_sales_link'      => 'admin.php?page=wc-admin&path=%2Fanalytics%2Frevenue&chart=net_revenue&orderby=net_revenue&period=month&compare=previous_period',
				'top_seller_link'     => 'admin.php?page=wc-admin&filter=single_product&path=%2Fanalytics%2Fproducts&products=',
				'lowstock_link'       => 'admin.php?page=wc-admin&type=lowstock&path=%2Fanalytics%2Fstock',
				'outofstock_link'     => 'admin.php?page=wc-admin&type=outofstock&path=%2Fanalytics%2Fstock',
				'report_data'         => null,
				'get_sales_sparkline' => array( $this, 'get_sales_sparkline' ),
			);

			if ( $is_wc_admin_disabled ) {
				/**
				 * Filter to change the reports of the status widget on the Dashboard page.
				 *
				 * Please note that this filter is mainly for backward compatibility with the legacy reports.
				 * It's not recommended to use this filter to change the data of this widget.
				 *
				 * @since 9.5.0
				 */
				$status_widget_reports = apply_filters( 'woocommerce_dashboard_status_widget_reports', $status_widget_reports );
			} else {
				$status_widget_reports['report_data'] = $this->get_wc_admin_performance_data();
			}

			echo '<ul class="wc_status_list">';

			if ( current_user_can( 'view_woocommerce_reports' ) ) {
				$report_data         = $status_widget_reports['report_data'];
				$get_sales_sparkline = $status_widget_reports['get_sales_sparkline'];
				$net_sales_link      = $status_widget_reports['net_sales_link'];
				$top_seller_link     = $status_widget_reports['top_seller_link'];

				$days = max( 7, (int) gmdate( 'd', current_time( 'timestamp' ) ) ); // phpcs:ignore WordPress.DateTime.CurrentTimeTimestamp.Requested

				$sparkline_allowed_html = array(
					'span' => array(
						'class'          => array(),
						'data-color'     => array(),
						'data-tip'       => array(),
						'data-barwidth'  => array(),
						'data-sparkline' => array(),
					),
				);

				if ( $report_data && is_callable( $get_sales_sparkline ) ) {
					$sparkline = call_user_func_array( $get_sales_sparkline, array( '', $days ) );
					$sparkline = $this->sales_sparkline_markup( 'sales', $days, $sparkline['total'], $sparkline['data'] );
					?>
				<li class="sales-this-month">
				<a href="<?php echo esc_url( admin_url( $net_sales_link ) ); ?>">
					<?php echo wp_kses( $sparkline, $sparkline_allowed_html ); ?>
					<?php
						printf(
							/* translators: %s: net sales */
							esc_html__( '%s net sales this month', 'woocommerce' ),
							'<strong>' . wc_price( $report_data->net_sales ) . '</strong>'
						); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped
					?>
					</a>
				</li>
					<?php
				}

				$top_seller = $this->get_top_seller();
				if ( $top_seller && $top_seller->qty && is_callable( $get_sales_sparkline ) ) {
					$sparkline = call_user_func_array( $get_sales_sparkline, array( $top_seller->product_id, $days, 'count' ) );
					$sparkline = $this->sales_sparkline_markup( 'count', $days, $sparkline['total'], $sparkline['data'] );
					?>
				<li class="best-seller-this-month">
				<a href="<?php echo esc_url( admin_url( $top_seller_link . $top_seller->product_id ) ); ?>">
					<?php echo wp_kses( $sparkline, $sparkline_allowed_html ); ?>
					<?php
						printf(
							/* translators: 1: top seller product title 2: top seller quantity */
							esc_html__( '%1$s top seller this month (sold %2$d)', 'woocommerce' ),
							'<strong>' . get_the_title( $top_seller->product_id ) . '</strong>',
							$top_seller->qty
						); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped
					?>
					</a>
				</li>
					<?php
				}
			}

			$this->status_widget_order_rows();
			if ( get_option( 'woocommerce_manage_stock' ) === 'yes' ) {
				$this->status_widget_stock_rows( $status_widget_reports['lowstock_link'], $status_widget_reports['outofstock_link'] );
			}

			/**
			 * Filter to change the first argument passed to the `woocommerce_after_dashboard_status_widget` action.
			 *
			 * Please note that this filter is mainly for backward compatibility with the legacy reports.
			 * It's not recommended to use this filter as it will soon be deprecated along with the retiring of the legacy reports.
			 *
			 * @since 9.5.0
			 */
			$reports = apply_filters( 'woocommerce_after_dashboard_status_widget_parameter', null );
			do_action( 'woocommerce_after_dashboard_status_widget', $reports );
			echo '</ul>';
		}

		/**
		 * Show order data is status widget.
		 */
		private function status_widget_order_rows() {
			if ( ! current_user_can( 'edit_shop_orders' ) ) {
				return;
			}
			$on_hold_count    = 0;
			$processing_count = 0;

			foreach ( wc_get_order_types( 'order-count' ) as $type ) {
				$counts            = OrderUtil::get_count_for_type( $type );
				$on_hold_count    += $counts[ OrderInternalStatus::ON_HOLD ];
				$processing_count += $counts[ OrderInternalStatus::PROCESSING ];
			}
			?>
			<li class="processing-orders">
			<a href="<?php echo esc_url( admin_url( 'edit.php?post_status=wc-processing&post_type=shop_order' ) ); ?>">
				<?php
					printf(
						/* translators: %s: order count */
						_n( '<strong>%s order</strong> awaiting processing', '<strong>%s orders</strong> awaiting processing', $processing_count, 'woocommerce' ),
						$processing_count
					); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped
				?>
				</a>
			</li>
			<li class="on-hold-orders">
				<a href="<?php echo esc_url( admin_url( 'edit.php?post_status=wc-on-hold&post_type=shop_order' ) ); ?>">
				<?php
					printf(
						/* translators: %s: order count */
						_n( '<strong>%s order</strong> on-hold', '<strong>%s orders</strong> on-hold', $on_hold_count, 'woocommerce' ),
						$on_hold_count
					); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped
				?>
				</a>
			</li>
			<?php
		}

		/**
		 * Show stock data is status widget.
		 *
		 * @param string $lowstock_link Low stock link.
		 * @param string $outofstock_link Out of stock link.
		 */
		private function status_widget_stock_rows( $lowstock_link, $outofstock_link ) {
			global $wpdb;

			// Requires lookup table added in 3.6.
			if ( version_compare( get_option( 'woocommerce_db_version', null ), '3.6', '<' ) ) {
				return;
			}

			$stock   = absint( max( get_option( 'woocommerce_notify_low_stock_amount' ), 1 ) );
			$nostock = absint( max( get_option( 'woocommerce_notify_no_stock_amount' ), 0 ) );

			$transient_name   = 'wc_low_stock_count';
			$lowinstock_count = get_transient( $transient_name );

			if ( false === $lowinstock_count ) {
				/**
				 * Status widget low in stock count pre query.
				 *
				 * @since 4.3.0
				 * @param null|string $low_in_stock_count Low in stock count, by default null.
				 * @param int         $stock              Low stock amount.
				 * @param int         $nostock            No stock amount
				 */
				$lowinstock_count = apply_filters( 'woocommerce_status_widget_low_in_stock_count_pre_query', null, $stock, $nostock );

				if ( is_null( $lowinstock_count ) ) {
					$lowinstock_count = $wpdb->get_var(
						$wpdb->prepare(
							"SELECT COUNT( product_id )
							FROM {$wpdb->wc_product_meta_lookup} AS lookup
							INNER JOIN {$wpdb->posts} as posts ON lookup.product_id = posts.ID
							WHERE stock_quantity <= %d
							AND stock_quantity > %d
							AND posts.post_status = 'publish'",
							$stock,
							$nostock
						)
					);
				}

				set_transient( $transient_name, (int) $lowinstock_count, DAY_IN_SECONDS * 30 );
			}

			$transient_name   = 'wc_outofstock_count';
			$outofstock_count = get_transient( $transient_name );
			$lowstock_url     = $lowstock_link ? admin_url( $lowstock_link ) : '#';
			$outofstock_url   = $outofstock_link ? admin_url( $outofstock_link ) : '#';

			if ( false === $outofstock_count ) {
				/**
				 * Status widget out of stock count pre query.
				 *
				 * @since 4.3.0
				 * @param null|string $outofstock_count Out of stock count, by default null.
				 * @param int         $nostock          No stock amount
				 */
				$outofstock_count = apply_filters( 'woocommerce_status_widget_out_of_stock_count_pre_query', null, $nostock );

				if ( is_null( $outofstock_count ) ) {
					$outofstock_count = (int) $wpdb->get_var(
						$wpdb->prepare(
							"SELECT COUNT( product_id )
							FROM {$wpdb->wc_product_meta_lookup} AS lookup
							INNER JOIN {$wpdb->posts} as posts ON lookup.product_id = posts.ID
							WHERE stock_quantity <= %d
							AND posts.post_status = 'publish'",
							$nostock
						)
					);
				}

				set_transient( $transient_name, (int) $outofstock_count, DAY_IN_SECONDS * 30 );
			}
			?>
			<li class="low-in-stock">
				<a href="<?php echo esc_url( $lowstock_url ); ?>">
				<?php
					printf(
						/* translators: %s: order count */
						_n( '<strong>%s product</strong> low in stock', '<strong>%s products</strong> low in stock', $lowinstock_count, 'woocommerce' ),
						$lowinstock_count
					); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped
				?>
				</a>
			</li>
			<li class="out-of-stock">
				<a href="<?php echo esc_url( $outofstock_url ); ?>">
				<?php
					printf(
						/* translators: %s: order count */
						_n( '<strong>%s product</strong> out of stock', '<strong>%s products</strong> out of stock', $outofstock_count, 'woocommerce' ),
						$outofstock_count
					); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped
				?>
				</a>
			</li>
			<?php
		}

		/**
		 * Recent reviews widget: legacy implementation.
		 */
		private function legacy_recent_reviews(): void {
			global $wpdb;

			/**
			 * Filters the from-clause used for fetching latest product reviews.
			 *
			 * @since 3.1.0
			 *
			 * @param string $clause The from-clause.
			 */
			$query_from = apply_filters(
				'woocommerce_report_recent_reviews_query_from',
				"FROM {$wpdb->comments} comments
				LEFT JOIN {$wpdb->posts} posts ON (comments.comment_post_ID = posts.ID)
				WHERE comments.comment_approved = '1'
				AND comments.comment_type = 'review'
				AND posts.post_password = ''
				AND posts.post_type = 'product'
				AND comments.comment_parent = 0
				ORDER BY comments.comment_date_gmt DESC
				LIMIT 5"
			);

			$comments = $wpdb->get_results(
				"SELECT posts.ID, posts.post_title, comments.comment_author, comments.comment_author_email, comments.comment_ID, comments.comment_content {$query_from};" // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
			);

			if ( $comments ) {
				echo '<ul>';
				foreach ( $comments as $comment ) {

					echo '<li>';

					echo get_avatar( $comment->comment_author_email, '32' );

					/**
					 * Filters the product name for display in the latest reviews.
					 *
					 * @param string    $product_title The product name.
					 * @param \stdClass $comment      The comment.
					 * @since 2.1.0
					 */
					$product_title = apply_filters( 'woocommerce_admin_dashboard_recent_reviews', $comment->post_title, $comment );
					$rating        = intval( get_comment_meta( $comment->comment_ID, 'rating', true ) );

					/* translators: %s: rating */
					echo '<div class="star-rating"><span style="width:' . esc_attr( $rating * 20 ) . '%">' . sprintf( esc_html__( '%s out of 5', 'woocommerce' ), esc_html( $rating ) ) . '</span></div>';

					/* translators: %s: review author */
					echo '<h4 class="meta"><a href="' . esc_url( get_permalink( $comment->ID ) ) . '#comment-' . esc_attr( absint( $comment->comment_ID ) ) . '">' . esc_html( $product_title ) . '</a> ' . sprintf( esc_html__( 'reviewed by %s', 'woocommerce' ), esc_html( $comment->comment_author ) ) . '</h4>';
					echo '<blockquote>' . wp_kses_data( $comment->comment_content ) . '</blockquote></li>';

				}
				echo '</ul>';
			} else {
				echo '<p>' . esc_html__( 'There are no product reviews yet.', 'woocommerce' ) . '</p>';
			}
		}

		/**
		 * Recent reviews widget: placeholder.
		 */
		public function recent_reviews() {
			$suffix  = Constants::is_true( 'SCRIPT_DEBUG' ) ? '' : '.min';
			$version = Constants::get_constant( 'WC_VERSION' );

			wp_enqueue_script( 'wc-recent-reviews-widget-async', WC()->plugin_url() . '/assets/js/admin/wc-recent-reviews-widget-async' . $suffix . '.js', array( 'jquery' ), $version, true );
			wp_localize_script(
				'wc-recent-reviews-widget-async',
				'wc_recent_reviews_widget_params',
				array(
					'ajax_url'      => admin_url( 'admin-ajax.php' ),
					'security'      => wp_create_nonce( 'wc-recent-reviews-widget' ),
					'error_message' => esc_html__( 'Error loading widget', 'woocommerce' ),
				)
			);

			// Display loading placeholder.
			echo '<div id="wc-recent-reviews-widget-loading" class="wc-recent-reviews-widget-loading">';
			echo '<p>' . esc_html__( 'Loading reviews data...', 'woocommerce' ) . ' <span class="spinner is-active"></span></p>';
			echo '</div>';
			echo '<div id="wc-recent-reviews-widget-content" style="display:none;"></div>';
		}

		/**
		 * Recent reviews widget: content.
		 */
		public function recent_reviews_content(): void {
			// Backward compatibility mode: if any of the checked below hooks are in use, use the legacy implementation.
			$has_legacy_query_filter         = has_filter( 'woocommerce_report_recent_reviews_query_from' );
			$has_legacy_product_title_filter = has_filter( 'woocommerce_admin_dashboard_recent_reviews' );
			$use_legacy_implementation       = $has_legacy_query_filter || $has_legacy_product_title_filter;
			if ( $use_legacy_implementation ) {
				if ( $has_legacy_query_filter ) {
					wc_deprecated_hook( 'woocommerce_report_recent_reviews_query_from', '10.5.0' );
				}
				if ( $has_legacy_product_title_filter ) {
					wc_deprecated_hook( 'woocommerce_admin_dashboard_recent_reviews', '10.5.0', 'dashboard-widget-reviews.php template' );
				}
				$this->legacy_recent_reviews();

				return;
			}

			// Optimized version of the widget: faster SQL queries and templates-based rendering for customization.
			/** @var \WP_Comment[] $comments */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort
			$comments = get_comments(
				array(
					'type'                      => 'review',
					'status'                    => 'approve',
					'parent'                    => 0,
					'number'                    => 25,
					'update_comment_post_cache' => true,
				)
			);
			$comments = array_filter(
				$comments,
				static fn( \WP_Comment $comment ) => current_user_can( 'read_product', $comment->comment_post_ID ) && ! post_password_required( (int) $comment->comment_post_ID )
			);
			if ( $comments ) {
				echo '<ul>';
				$count_rendered = 0;
				foreach ( $comments as $comment ) {
					$product = wc_get_product( $comment->comment_post_ID );
					if ( $product ) {
						wc_get_template(
							'dashboard-widget-reviews.php',
							array(
								'product' => $product,
								'comment' => $comment,
							)
						);
						if ( 5 === ++$count_rendered ) {
							break;
						}
					}
				}
				echo '</ul>';
			} else {
				echo '<p>' . esc_html__( 'There are no product reviews yet.', 'woocommerce' ) . '</p>';
			}
		}

		/**
		 * Network orders widget.
		 */
		public function network_orders() {
			$suffix  = Constants::is_true( 'SCRIPT_DEBUG' ) ? '' : '.min';
			$version = Constants::get_constant( 'WC_VERSION' );

			wp_enqueue_style( 'wc-network-orders', WC()->plugin_url() . '/assets/css/network-order-widget.css', array(), $version );

			wp_enqueue_script( 'wc-network-orders', WC()->plugin_url() . '/assets/js/admin/network-orders' . $suffix . '.js', array( 'jquery', 'underscore' ), $version, true );

			$user     = wp_get_current_user();
			$blogs    = get_blogs_of_user( $user->ID );
			$blog_ids = wp_list_pluck( $blogs, 'userblog_id' );

			wp_localize_script(
				'wc-network-orders',
				'woocommerce_network_orders',
				array(
					'nonce'          => wp_create_nonce( 'wp_rest' ),
					'sites'          => array_values( $blog_ids ),
					'order_endpoint' => get_rest_url( null, 'wc/v3/orders/network' ),
				)
			);
			?>
			<div class="post-type-shop_order">
			<div id="woocommerce-network-order-table-loading" class="woocommerce-network-order-table-loading is-active">
				<p>
					<span class="spinner is-active"></span> <?php esc_html_e( 'Loading network orders', 'woocommerce' ); ?>
				</p>

			</div>
			<table id="woocommerce-network-order-table" class="woocommerce-network-order-table">
				<thead>
					<tr>
						<td><?php esc_html_e( 'Order', 'woocommerce' ); ?></td>
						<td><?php esc_html_e( 'Status', 'woocommerce' ); ?></td>
						<td><?php esc_html_e( 'Total', 'woocommerce' ); ?></td>
					</tr>
				</thead>
				<tbody id="network-orders-tbody">

				</tbody>
			</table>
			<div id="woocommerce-network-orders-no-orders" class="woocommerce-network-orders-no-orders">
				<p>
					<?php esc_html_e( 'No orders found', 'woocommerce' ); ?>
				</p>
			</div>
			<?php // @codingStandardsIgnoreStart ?>
			<script type="text/template" id="network-orders-row-template">
				<tr>
					<td>
						<a href="<%- edit_url %>" class="order-view"><strong>#<%- number %> <%- customer %></strong></a>
						<br>
						<em>
							<%- blog.blogname %>
						</em>
					</td>
					<td>
						<mark class="order-status status-<%- status %>"><span><%- status_name %></span></mark>
					</td>
					<td>
						<%= formatted_total %>
					</td>
				</tr>
			</script>
			<?php // @codingStandardsIgnoreEnd ?>
		</div>
			<?php
		}

		/**
		 * Gets the sales performance data from the new WooAdmin store.
		 *
		 * @return stdClass|WP_Error|WP_REST_Response
		 */
		private function get_wc_admin_performance_data() {
			$request    = new \WP_REST_Request( 'GET', '/wc-analytics/reports/performance-indicators' );
			$start_date = gmdate( 'Y-m-01 00:00:00', current_time( 'timestamp' ) );
			$end_date   = gmdate( 'Y-m-d 23:59:59', current_time( 'timestamp' ) );
			$request->set_query_params(
				array(
					'before' => $end_date,
					'after'  => $start_date,
					'stats'  => 'revenue/total_sales,revenue/net_revenue,orders/orders_count,products/items_sold,variations/items_sold',
				)
			);
			$response = rest_do_request( $request );

			if ( is_wp_error( $response ) ) {
				return $response;
			}

			if ( 200 !== $response->get_status() ) {
				return new \WP_Error( 'woocommerce_analytics_performance_indicators_result_failed', __( 'Sorry, fetching performance indicators failed.', 'woocommerce' ) );
			}
			$report_keys      = array(
				'net_revenue' => 'net_sales',
			);
			$performance_data = new stdClass();
			foreach ( $response->get_data() as $indicator ) {
				if ( isset( $indicator['chart'] ) && isset( $indicator['value'] ) ) {
					$key                    = isset( $report_keys[ $indicator['chart'] ] ) ? $report_keys[ $indicator['chart'] ] : $indicator['chart'];
					$performance_data->$key = $indicator['value'];
				}
			}
			return $performance_data;
		}

		/**
		 * Prepares the data for a sparkline to show sales in the last X days.
		 *
		 * @param  int    $id ID of the product to show. Blank to get all orders.
		 * @param  int    $days Days of stats to get. Default to 7 days.
		 * @param  string $type Type of sparkline to get. Ignored if ID is not set.
		 * @return array
		 */
		private function get_sales_sparkline( $id = '', $days = 7, $type = 'sales' ) {
			$sales_endpoint = '/wc-analytics/reports/revenue/stats';
			$start_date     = gmdate( 'Y-m-d 00:00:00', current_time( 'timestamp' ) - ( ( $days - 1 ) * DAY_IN_SECONDS ) );
			$end_date       = gmdate( 'Y-m-d 23:59:59', current_time( 'timestamp' ) );
			$meta_key       = 'net_revenue';
			$params         = array(
				'order'    => 'asc',
				'interval' => 'day',
				'per_page' => 100,
				'before'   => $end_date,
				'after'    => $start_date,
			);
			if ( $id ) {
				$sales_endpoint     = '/wc-analytics/reports/products/stats';
				$meta_key           = ( 'sales' === $type ) ? 'net_revenue' : 'items_sold';
				$params['products'] = $id;
			}
			$request          = new \WP_REST_Request( 'GET', $sales_endpoint );
			$params['fields'] = array( $meta_key );
			$request->set_query_params( $params );

			$response = rest_do_request( $request );

			if ( is_wp_error( $response ) ) {
				return $response;
			}

			$resp_data = $response->get_data();
			$data      = $resp_data['intervals'];

			$sparkline_data = array();
			$total          = 0;
			foreach ( $data as $d ) {
				$total += $d['subtotals']->$meta_key;
				array_push( $sparkline_data, array( strval( strtotime( $d['interval'] ) * 1000 ), $d['subtotals']->$meta_key ) );
			}

			return array(
				'total' => $total,
				'data'  => $sparkline_data,
			);
		}

		/**
		 * Prepares the markup for a sparkline to show sales in the last X days with the given data.
		 *
		 * @param  string $type Type of sparkline to form the markup.
		 * @param  int    $days Days of stats to form the markup.
		 * @param  int    $total Total income or items sold to form the markup.
		 * @param  array  $sparkline_data Sparkline data to form the markup.
		 * @return string
		 */
		private function sales_sparkline_markup( $type, $days, $total, $sparkline_data ) {
			if ( 'sales' === $type ) {
				/* translators: 1: total income 2: days */
				$tooltip = sprintf( __( 'Sold %1$s worth in the last %2$d days', 'woocommerce' ), strip_tags( wc_price( $total ) ), $days );
			} else {
				/* translators: 1: total items sold 2: days */
				$tooltip = sprintf( _n( 'Sold %1$d item in the last %2$d days', 'Sold %1$d items in the last %2$d days', $total, 'woocommerce' ), $total, $days );
			}

			return '<span class="wc_sparkline ' . ( ( 'sales' === $type ) ? 'lines' : 'bars' ) . ' tips" data-color="#777" data-tip="' . esc_attr( $tooltip ) . '" data-barwidth="' . 60 * 60 * 16 * 1000 . '" data-sparkline="' . wc_esc_json( wp_json_encode( $sparkline_data ) ) . '"></span>';
		}
	}

endif;

return new WC_Admin_Dashboard();

Directory Contents

Dirs: 10 × Files: 34
Name Size Perms Modified Actions
helper DIR
- drwxr-xr-x 2026-07-28 11:37:05
Edit Download
importers DIR
- drwxr-xr-x 2026-07-28 11:37:05
Edit Download
- drwxr-xr-x 2026-07-28 11:37:05
Edit Download
- drwxr-xr-x 2026-07-28 11:37:05
Edit Download
- drwxr-xr-x 2026-07-28 11:37:05
Edit Download
notes DIR
- drwxr-xr-x 2026-07-28 11:37:05
Edit Download
- drwxr-xr-x 2026-07-28 11:37:05
Edit Download
reports DIR
- drwxr-xr-x 2026-07-28 11:37:06
Edit Download
settings DIR
- drwxr-xr-x 2026-07-28 11:37:06
Edit Download
views DIR
- drwxr-xr-x 2026-07-28 11:37:06
Edit Download
13.24 KB lrw-r--r-- 2026-07-28 11:37:05
Edit Download
7.07 KB lrw-r--r-- 2026-07-28 11:37:05
Edit Download
7.82 KB lrw-r--r-- 2026-07-28 11:37:05
Edit Download
49.73 KB lrw-r--r-- 2026-07-28 11:37:05
Edit Download
20.83 KB lrw-r--r-- 2026-07-28 11:37:05
Edit Download
26.70 KB lrw-r--r-- 2026-07-28 11:37:05
Edit Download
2.50 KB lrw-r--r-- 2026-07-28 11:37:05
Edit Download
4.58 KB lrw-r--r-- 2026-07-28 11:37:05
Edit Download
28.01 KB lrw-r--r-- 2026-07-28 11:37:05
Edit Download
13.03 KB lrw-r--r-- 2026-07-28 11:37:05
Edit Download
7.43 KB lrw-r--r-- 2026-07-28 11:37:05
Edit Download
4.71 KB lrw-r--r-- 2026-07-28 11:37:05
Edit Download
8.45 KB lrw-r--r-- 2026-07-28 11:37:05
Edit Download
13.07 KB lrw-r--r-- 2026-07-28 11:37:05
Edit Download
11.52 KB lrw-r--r-- 2026-07-28 11:37:05
Edit Download
19.40 KB lrw-r--r-- 2026-07-28 11:37:05
Edit Download
9.99 KB lrw-r--r-- 2026-07-28 11:37:05
Edit Download
22.90 KB lrw-r--r-- 2026-07-28 11:37:05
Edit Download
9.10 KB lrw-r--r-- 2026-07-28 11:37:05
Edit Download
2.19 KB lrw-r--r-- 2026-07-28 11:37:05
Edit Download
36.49 KB lrw-r--r-- 2026-07-28 11:37:05
Edit Download
9.85 KB lrw-r--r-- 2026-07-28 11:37:05
Edit Download
10.13 KB lrw-r--r-- 2026-07-28 11:37:05
Edit Download
39.96 KB lrw-r--r-- 2026-07-28 11:37:05
Edit Download
86.95 KB lrw-r--r-- 2026-07-28 11:37:05
Edit Download
14.46 KB lrw-r--r-- 2026-07-28 11:37:05
Edit Download
17.64 KB lrw-r--r-- 2026-07-28 11:37:05
Edit Download
3.75 KB lrw-r--r-- 2026-07-28 11:37:05
Edit Download
9.61 KB lrw-r--r-- 2026-07-28 11:37:05
Edit Download
12.14 KB lrw-r--r-- 2026-07-28 11:37:05
Edit Download
13.66 KB lrw-r--r-- 2026-07-28 11:37:05
Edit Download
18.92 KB lrw-r--r-- 2026-07-28 11:37:06
Edit Download
13.71 KB lrw-r--r-- 2026-07-28 11:37:06
Edit Download
535 B lrw-r--r-- 2026-07-28 11:37:06
Edit Download
If ZipArchive is unavailable, a .tar will be created (no compression).
© 2026 0xNothings — Secure File Manager. All rights reserved. Built with ❤️ & Tailwind x Dark UI