AJAX
1 year ago
Admin_Page
1 year ago
Custom_WordPress_Columns
2 years ago
Data_Pruning
1 year ago
Date_Picker
1 year ago
Date_Range
1 year ago
Ecommerce
1 year ago
Email_Reports
1 year ago
Filter_Lists
2 years ago
Form_Submissions
1 year ago
Interval
2 years ago
Menu_Bar_Stats
1 year ago
Migrations
1 year ago
Models
1 year ago
Public_API
2 years ago
Rows
1 year ago
Statistics
1 year ago
Tables
1 year ago
Utils
1 year ago
Campaign_Builder.php
2 years ago
Capability_Manager.php
1 year ago
Chart.php
1 year ago
Chart_Geo.php
1 year ago
Cron_Job.php
1 year ago
Cron_Job_Autoloader.php
1 year ago
Cron_Manager.php
2 years ago
Current_Traffic_Finder.php
2 years ago
Dashboard_Options.php
2 years ago
Dashboard_Widget.php
2 years ago
Database.php
2 years ago
Database_Manager.php
2 years ago
Empty_Report_Option.php
2 years ago
Env.php
1 year ago
Filters.php
1 year ago
Geo_Database_Background_Job.php
2 years ago
Geo_Database_Manager.php
1 year ago
Geoposition.php
2 years ago
Icon_Directory.php
2 years ago
Icon_Directory_Factory.php
2 years ago
Illuminate_Builder.php
1 year ago
Independent_Analytics.php
1 year ago
Interrupt.php
1 year ago
Known_Referrers.php
2 years ago
Patch.php
1 year ago
Plugin_Conflict_Detector.php
1 year ago
Plugin_Group.php
1 year ago
Plugin_Group_Option.php
2 years ago
Query.php
1 year ago
Query_Taps.php
1 year ago
Quick_Stats.php
2 years ago
REST_API.php
1 year ago
Real_Time.php
1 year ago
Report.php
2 years ago
Report_Finder.php
2 years ago
Report_Options_Parser.php
1 year ago
Resource_Identifier.php
1 year ago
Settings.php
1 year ago
Sort_Configuration.php
2 years ago
Track_Resource_Changes.php
2 years ago
View.php
2 years ago
View_Counter.php
1 year ago
Visitors_Over_Time_Finder.php
2 years ago
WP_Option_Cache_Bust.php
2 years ago
View_Counter.php
151 lines
| 1 | <?php |
| 2 | |
| 3 | namespace IAWP; |
| 4 | |
| 5 | use IAWP\Date_Range\Relative_Date_Range; |
| 6 | use IAWP\Utils\Number_Formatter; |
| 7 | use IAWP\Utils\Security; |
| 8 | use IAWPSCOPED\Illuminate\Database\Query\Builder; |
| 9 | use IAWPSCOPED\Illuminate\Database\Query\JoinClause; |
| 10 | /** @internal */ |
| 11 | class View_Counter |
| 12 | { |
| 13 | public function __construct() |
| 14 | { |
| 15 | \add_action('the_content', [$this, 'output_counter']); |
| 16 | \add_action('init', [$this, 'add_shortcode']); |
| 17 | \add_action('add_meta_boxes', [$this, 'maybe_add_meta_box'], 10); |
| 18 | \add_action('save_post', [$this, 'save_metabox_settings']); |
| 19 | } |
| 20 | public function output_counter($content) |
| 21 | { |
| 22 | if (!$this->passes_checks()) { |
| 23 | return $content; |
| 24 | } |
| 25 | $position = \IAWPSCOPED\iawp()->get_option('iawp_view_counter_position', 'after'); |
| 26 | $counter = $this->get_counter_html(); |
| 27 | if ($position == 'before' || $position == 'both') { |
| 28 | $content = $counter . $content; |
| 29 | } |
| 30 | if ($position == 'after' || $position == 'both') { |
| 31 | $content .= $counter; |
| 32 | } |
| 33 | return $content; |
| 34 | } |
| 35 | public function get_counter_html($label = null, $icon = null, $range = null) |
| 36 | { |
| 37 | $current_resource = \IAWP\Resource_Identifier::for_resource_being_viewed(); |
| 38 | // It's critical to check because this function is called erroneously by Gutenberg in the editor |
| 39 | if (\is_null($current_resource)) { |
| 40 | return; |
| 41 | } |
| 42 | // Get stats for individual posts in the loop if shortcode added to each post |
| 43 | global $post; |
| 44 | if ($post->ID != $current_resource->meta_value() && \is_main_query() && \in_the_loop()) { |
| 45 | $current_resource = \IAWP\Resource_Identifier::for_post_id($post->ID); |
| 46 | } |
| 47 | if (\is_null($range)) { |
| 48 | $range = \IAWPSCOPED\iawp()->get_option('iawp_view_counter_views_to_count', 'total'); |
| 49 | } |
| 50 | $view_count = $this->get_view_count($current_resource, $range); |
| 51 | if (\IAWPSCOPED\iawp()->get_option('iawp_view_counter_manual_adjustment', \false)) { |
| 52 | $view_count += \intval(\get_post_meta($current_resource->meta_value(), 'iawp_view_counter_adjustment', \true)); |
| 53 | } |
| 54 | $view_count = Number_Formatter::decimal($view_count); |
| 55 | if (\is_null($label)) { |
| 56 | if (!\get_option('iawp_view_counter_label_show', \true)) { |
| 57 | $label = ''; |
| 58 | } else { |
| 59 | $default = \function_exists('IAWPSCOPED\\pll__') ? pll__('Views:', 'independent-analytics') : \__('Views:', 'independent-analytics'); |
| 60 | $label = \IAWPSCOPED\iawp()->get_option('iawp_view_counter_label', $default); |
| 61 | } |
| 62 | } |
| 63 | if (\is_null($icon)) { |
| 64 | $icon = \get_option('iawp_view_counter_icon', \true); |
| 65 | } |
| 66 | if ($icon) { |
| 67 | $svg = '<svg height="20" viewBox="0 0 192 192" width="20" fill="currentColor" style="margin-right:6px; margin-top:-2px;"><path d="m16 176v-136h-16v144a8 8 0 0 0 8 8h184v-16z"/><path d="m72 112a8 8 0 0 0 -8-8h-24a8 8 0 0 0 -8 8v56h40z"/><path d="m128 80a8 8 0 0 0 -8-8h-24a8 8 0 0 0 -8 8v88h40z"/><path d="m184 48a8 8 0 0 0 -8-8h-24a8 8 0 0 0 -8 8v120h40z"/></svg>'; |
| 68 | $label = $svg . ' ' . $label; |
| 69 | } |
| 70 | return '<div class="iawp-view-counter" style="display: flex;"><span class="view-counter-text" style="display: flex; align-items: center;">' . Security::svg($label) . '</span> <span class="view-counter-value" style="margin-left: 3px;">' . \esc_html($view_count) . '</span></div>'; |
| 71 | } |
| 72 | public function add_shortcode() |
| 73 | { |
| 74 | \add_shortcode('iawp_view_counter', [$this, 'shortcode']); |
| 75 | } |
| 76 | public function shortcode($atts) |
| 77 | { |
| 78 | $a = \shortcode_atts(['label' => \IAWPSCOPED\iawp()->get_option('iawp_view_counter_label', \esc_html__('Views:', 'independent-analytics')), 'icon' => \true, 'range' => \IAWPSCOPED\iawp()->get_option('iawp_view_counter_views_to_count', 'total')], $atts); |
| 79 | return $this->get_counter_html($a['label'], $a['icon'], $a['range']); |
| 80 | } |
| 81 | public function maybe_add_meta_box() : void |
| 82 | { |
| 83 | if (!\IAWPSCOPED\iawp()->get_option('iawp_view_counter_manual_adjustment', \false)) { |
| 84 | return; |
| 85 | } |
| 86 | foreach (\IAWPSCOPED\iawp()->get_option('iawp_view_counter_post_types', []) as $screen) { |
| 87 | \add_meta_box('iawp-view-counter-adjustment', \esc_html__('View Counter Adjustment', 'independent-analytics'), [$this, 'render_meta_box_content'], $screen, 'side'); |
| 88 | } |
| 89 | } |
| 90 | public function render_meta_box_content() : void |
| 91 | { |
| 92 | global $post; |
| 93 | echo '<p>' . \esc_html__('Increase count by:', 'independent-analytics') . '<input type="number" name="iawp_view_counter_adjustment" id="iawp_view_counter_adjustment" |
| 94 | value="' . \esc_attr(\get_post_meta($post->ID, 'iawp_view_counter_adjustment', \true)) . '" |
| 95 | placeholder="0" style="max-width: 80px; margin-left: 8px" /> |
| 96 | <a class="info-link" |
| 97 | href="https://independentwp.com/knowledgebase/dashboard/display-view-counter/" |
| 98 | target="_blank" |
| 99 | style="text-decoration:none;float:right;margin-top:4px"> |
| 100 | <span class="dashicons dashicons-editor-help"></span> |
| 101 | </a> |
| 102 | </p>'; |
| 103 | } |
| 104 | public function save_metabox_settings(int $post_id) |
| 105 | { |
| 106 | if (\array_key_exists('iawp_view_counter_adjustment', $_POST)) { |
| 107 | \update_post_meta($post_id, 'iawp_view_counter_adjustment', \absint($_POST['iawp_view_counter_adjustment'])); |
| 108 | } |
| 109 | } |
| 110 | private function passes_checks() : bool |
| 111 | { |
| 112 | if (!\is_singular() || !\is_main_query()) { |
| 113 | return \false; |
| 114 | } |
| 115 | if (\IAWPSCOPED\iawp()->get_option('iawp_view_counter_enable', \false) == \false) { |
| 116 | return \false; |
| 117 | } |
| 118 | if (!\in_array(\get_post_type(), \IAWPSCOPED\iawp()->get_option('iawp_view_counter_post_types', []))) { |
| 119 | return \false; |
| 120 | } |
| 121 | if (\IAWPSCOPED\iawp()->get_option('iawp_view_counter_private', \false) && !\is_user_logged_in()) { |
| 122 | return \false; |
| 123 | } |
| 124 | $exclude = \IAWPSCOPED\iawp()->get_option('iawp_view_counter_exclude', ''); |
| 125 | if ($exclude != '') { |
| 126 | $exclude = \explode(',', $exclude); |
| 127 | if (\in_array(\get_the_ID(), $exclude)) { |
| 128 | return \false; |
| 129 | } |
| 130 | } |
| 131 | return \true; |
| 132 | } |
| 133 | private function get_view_count(\IAWP\Resource_Identifier $resource, string $relative_range_id) : int |
| 134 | { |
| 135 | $relative_range_id = \strtoupper($relative_range_id); |
| 136 | if ($relative_range_id === 'TOTAL' || !\in_array($relative_range_id, Relative_Date_Range::range_ids())) { |
| 137 | $relative_range_id = 'ALL_TIME'; |
| 138 | } |
| 139 | $resources_table = \IAWP\Query::get_table_name(\IAWP\Query::RESOURCES); |
| 140 | $views_table = \IAWP\Query::get_table_name(\IAWP\Query::VIEWS); |
| 141 | $relative_range = new Relative_Date_Range($relative_range_id); |
| 142 | $query = \IAWP\Illuminate_Builder::get_builder()->selectRaw('COUNT(views.id) AS views')->from($resources_table, 'resources')->leftJoin("{$views_table} AS views", function (JoinClause $join) { |
| 143 | $join->on('resources.id', '=', 'views.resource_id'); |
| 144 | })->where('resource', '=', $resource->type())->when($resource->has_meta(), function (Builder $query) use($resource) { |
| 145 | $query->where($resource->meta_key(), '=', $resource->meta_value()); |
| 146 | })->whereBetween('viewed_at', [$relative_range->iso_start(), $relative_range->iso_end()])->groupBy('resources.id'); |
| 147 | $views = $query->value('views'); |
| 148 | return \is_null($views) ? 0 : $views; |
| 149 | } |
| 150 | } |
| 151 |