Click.php
8 months ago
Click_Processing_Job.php
5 months ago
Config_File_Manager.php
1 year ago
Link_Rule.php
1 year ago
Link_Rule_Finder.php
9 months ago
Link_Rule_Finder.php
186 lines
| 1 | <?php |
| 2 | |
| 3 | namespace IAWP\Click_Tracking; |
| 4 | |
| 5 | use IAWP\Illuminate_Builder; |
| 6 | use IAWP\Tables; |
| 7 | use IAWP\Utils\URL; |
| 8 | use IAWPSCOPED\Illuminate\Support\Collection; |
| 9 | use IAWPSCOPED\Illuminate\Support\Str; |
| 10 | // TODO - This for more link a matcher and not a finder... |
| 11 | /** @internal */ |
| 12 | class Link_Rule_Finder |
| 13 | { |
| 14 | private $protocol; |
| 15 | private $href; |
| 16 | private $classes; |
| 17 | private $ids; |
| 18 | private static $database_records = null; |
| 19 | public function __construct(?string $protocol, ?string $href, string $classes, string $ids) |
| 20 | { |
| 21 | $this->protocol = $protocol; |
| 22 | $this->href = $href; |
| 23 | $this->classes = $classes; |
| 24 | $this->ids = $ids; |
| 25 | } |
| 26 | public function links() : ?Collection |
| 27 | { |
| 28 | return self::get_database_records()->filter(function ($link_rule) { |
| 29 | return $link_rule->is_active(); |
| 30 | })->filter(function ($link_rule) { |
| 31 | return $this->is_match($link_rule); |
| 32 | })->values(); |
| 33 | } |
| 34 | private function is_match($link_rule) : bool |
| 35 | { |
| 36 | switch ($link_rule->type()) { |
| 37 | case 'class': |
| 38 | return $this->is_matching_class($link_rule); |
| 39 | case 'id': |
| 40 | return $this->is_matching_id($link_rule); |
| 41 | case 'domain': |
| 42 | return $this->is_matching_domain($link_rule); |
| 43 | case 'extension': |
| 44 | return $this->is_matching_extension($link_rule); |
| 45 | case 'subdirectory': |
| 46 | return $this->is_matching_subdirectory($link_rule); |
| 47 | case 'protocol': |
| 48 | return $this->is_matching_protocol($link_rule); |
| 49 | case 'external': |
| 50 | return $this->is_matching_external($link_rule); |
| 51 | default: |
| 52 | return \false; |
| 53 | } |
| 54 | } |
| 55 | private function is_matching_class($link_rule) : bool |
| 56 | { |
| 57 | if ($this->classes === "") { |
| 58 | return \false; |
| 59 | } |
| 60 | return Collection::make(\explode(' ', $this->classes))->contains(function ($value, $key) use($link_rule) { |
| 61 | return $link_rule->value() === $value; |
| 62 | }); |
| 63 | } |
| 64 | private function is_matching_id($link_rule) : bool |
| 65 | { |
| 66 | if ($this->ids === "") { |
| 67 | return \false; |
| 68 | } |
| 69 | return Collection::make(\explode(' ', $this->ids))->contains(function ($value, $key) use($link_rule) { |
| 70 | return $link_rule->value() === $value; |
| 71 | }); |
| 72 | } |
| 73 | private function is_matching_domain($link_rule) : bool |
| 74 | { |
| 75 | if (\is_null($this->href)) { |
| 76 | return \false; |
| 77 | } |
| 78 | $url = new URL($this->href); |
| 79 | if (!$url->is_valid_url()) { |
| 80 | return \false; |
| 81 | } |
| 82 | $domain = $url->get_domain(); |
| 83 | $domains = [$domain]; |
| 84 | if (Str::startsWith($domain, 'www.')) { |
| 85 | $domains[] = Str::after($domain, 'www.'); |
| 86 | } else { |
| 87 | $domains[] = 'www.' . $domain; |
| 88 | } |
| 89 | return \in_array($link_rule->value(), $domains); |
| 90 | } |
| 91 | private function is_matching_extension($link_rule) : bool |
| 92 | { |
| 93 | if (\is_null($this->href)) { |
| 94 | return \false; |
| 95 | } |
| 96 | $url = new URL($this->href); |
| 97 | if (!$url->is_valid_url()) { |
| 98 | return \false; |
| 99 | } |
| 100 | return $link_rule->value() === $url->get_extension(); |
| 101 | } |
| 102 | private function is_matching_subdirectory($link_rule) : bool |
| 103 | { |
| 104 | if (\is_null($this->href)) { |
| 105 | return \false; |
| 106 | } |
| 107 | $url = URL::new($this->href); |
| 108 | $site_url = URL::new(\get_site_url()); |
| 109 | if (!$url->is_valid_url() || $url->get_domain() !== $site_url->get_domain()) { |
| 110 | return \false; |
| 111 | } |
| 112 | $path = $url->get_path(); |
| 113 | $path_parts = Collection::make(\explode('/', $path))->filter()->values(); |
| 114 | if ($path_parts->isEmpty()) { |
| 115 | return \false; |
| 116 | } |
| 117 | return $link_rule->value() === $path_parts->first(); |
| 118 | } |
| 119 | private function is_matching_protocol($link_rule) : bool |
| 120 | { |
| 121 | if (\is_null($this->href)) { |
| 122 | return \false; |
| 123 | } |
| 124 | return $this->protocol === $link_rule->value(); |
| 125 | } |
| 126 | private function is_matching_external($link_rule) : bool |
| 127 | { |
| 128 | if (\is_null($this->href)) { |
| 129 | return \false; |
| 130 | } |
| 131 | $site_url = URL::new(\get_site_url()); |
| 132 | $link_url = URL::new($this->href); |
| 133 | // Only track valid http/https URLs and not other protocols like mailto:, tel:, etc |
| 134 | if (!$link_url->is_valid_url()) { |
| 135 | return \false; |
| 136 | } |
| 137 | return $link_url->get_domain() !== $site_url->get_domain(); |
| 138 | } |
| 139 | public static function new(?string $protocol, ?string $href, string $classes, ?string $id) : self |
| 140 | { |
| 141 | return new self($protocol, $href, $classes, $id); |
| 142 | } |
| 143 | public static function link_rules() : Collection |
| 144 | { |
| 145 | return self::get_database_records(); |
| 146 | } |
| 147 | public static function active_link_rules() : Collection |
| 148 | { |
| 149 | return self::get_database_records()->filter(function ($link_rule) { |
| 150 | return $link_rule->is_active(); |
| 151 | })->values(); |
| 152 | } |
| 153 | public static function inactive_link_rules() : Collection |
| 154 | { |
| 155 | return self::get_database_records()->filter(function ($link_rule) { |
| 156 | return !$link_rule->is_active(); |
| 157 | })->values(); |
| 158 | } |
| 159 | public static function cached_link_rules() : array |
| 160 | { |
| 161 | $cached_rules = \get_option('iawp_link_rules', \false); |
| 162 | if (!\is_array($cached_rules)) { |
| 163 | $link_rules = \IAWP\Click_Tracking\Link_Rule_Finder::active_link_rules()->map(function (\IAWP\Click_Tracking\Link_Rule $link_rule) { |
| 164 | return ['type' => $link_rule->type(), 'value' => $link_rule->value()]; |
| 165 | }); |
| 166 | \update_option('iawp_link_rules', $link_rules->all()); |
| 167 | } |
| 168 | return \get_option('iawp_link_rules'); |
| 169 | } |
| 170 | public static function require_cleared_cache() |
| 171 | { |
| 172 | \delete_option('iawp_click_tracking_cache_cleared'); |
| 173 | \delete_option('iawp_link_rules'); |
| 174 | } |
| 175 | private static function get_database_records() : Collection |
| 176 | { |
| 177 | if (\is_null(static::$database_records)) { |
| 178 | $records = Illuminate_Builder::new()->from(Tables::link_rules())->orderBy('position')->orderByDesc('created_at')->get(); |
| 179 | static::$database_records = $records->map(function ($link_rule) { |
| 180 | return new \IAWP\Click_Tracking\Link_Rule($link_rule); |
| 181 | }); |
| 182 | } |
| 183 | return static::$database_records; |
| 184 | } |
| 185 | } |
| 186 |