Click.php
1 year ago
Click_Processing_Job.php
1 year ago
Config_File_Manager.php
1 year ago
Link_Rule.php
1 year ago
Link_Rule_Finder.php
1 year ago
Click_Processing_Job.php
89 lines
| 1 | <?php |
| 2 | |
| 3 | namespace IAWP\Click_Tracking; |
| 4 | |
| 5 | use IAWP\Cron_Job; |
| 6 | use IAWP\Models\Visitor; |
| 7 | use IAWP\Payload_Validator; |
| 8 | use IAWP\Utils\Security; |
| 9 | use IAWPSCOPED\Illuminate\Support\Str; |
| 10 | /** @internal */ |
| 11 | class Click_Processing_Job extends Cron_Job |
| 12 | { |
| 13 | protected $name = 'iawp_click_processing'; |
| 14 | protected $interval = 'every_minute'; |
| 15 | public function handle() : void |
| 16 | { |
| 17 | // Periodically recreate the config file |
| 18 | \IAWP\Click_Tracking\Config_File_Manager::recreate(); |
| 19 | if (\IAWPSCOPED\iawp_is_free()) { |
| 20 | self::unschedule(); |
| 21 | return; |
| 22 | } |
| 23 | $click_data_file = $this->get_click_data_file(); |
| 24 | if ($click_data_file === null) { |
| 25 | return; |
| 26 | } |
| 27 | $job_file = $this->create_job_file($click_data_file); |
| 28 | if ($job_file === null) { |
| 29 | return; |
| 30 | } |
| 31 | $job_handle = \fopen($job_file, 'r'); |
| 32 | if ($job_handle === \false) { |
| 33 | return; |
| 34 | } |
| 35 | // The first line for the PHP file is an exit statement to keep the contents private. This |
| 36 | // should be skipped when parsing the file. |
| 37 | if (\pathinfo($job_file, \PATHINFO_EXTENSION) === 'php') { |
| 38 | \fgets($job_handle); |
| 39 | // Skip first line |
| 40 | } |
| 41 | while (($json = \fgets($job_handle)) !== \false) { |
| 42 | $event = \json_decode($json, \true); |
| 43 | $event['href'] = \sanitize_url($event['href']); |
| 44 | $event['classes'] = Security::string($event['classes']); |
| 45 | $event['ids'] = Security::string($event['ids']); |
| 46 | if (\is_null($event)) { |
| 47 | continue; |
| 48 | } |
| 49 | $payload_validator = Payload_Validator::new($event['payload'], $event['signature']); |
| 50 | if (!$payload_validator->is_valid() || \is_null($payload_validator->resource())) { |
| 51 | continue; |
| 52 | } |
| 53 | $click = \IAWP\Click_Tracking\Click::new(['href' => $event['href'], 'classes' => $event['classes'], 'ids' => $event['ids'], 'resource_id' => $payload_validator->resource()['id'], 'visitor_id' => Visitor::fetch_visitor_id_by_hash($event['visitor_token']), 'created_at' => \DateTime::createFromFormat('U', $event['created_at'])]); |
| 54 | $click->track(); |
| 55 | } |
| 56 | \fclose($job_handle); |
| 57 | \unlink($job_file); |
| 58 | } |
| 59 | private function get_click_data_file() : ?string |
| 60 | { |
| 61 | $avoid_temporary_directory = \defined('IAWP_AVOID_TEMPORARY_DIRECTORY') ? \IAWP_AVOID_TEMPORARY_DIRECTORY === \true : \false; |
| 62 | if (!$avoid_temporary_directory) { |
| 63 | $text_file = Str::finish(\sys_get_temp_dir(), \DIRECTORY_SEPARATOR) . "iawp-click-data.txt"; |
| 64 | if (\is_file($text_file) && \is_readable($text_file) && \is_writable($text_file)) { |
| 65 | return $text_file; |
| 66 | } |
| 67 | } |
| 68 | $php_file = \IAWPSCOPED\iawp_path_to('iawp-click-data.php'); |
| 69 | if (\is_file($php_file)) { |
| 70 | return $php_file; |
| 71 | } |
| 72 | return null; |
| 73 | } |
| 74 | private function create_job_file(string $file) : ?string |
| 75 | { |
| 76 | if (!\is_readable($file) || !\is_writable($file)) { |
| 77 | return null; |
| 78 | } |
| 79 | $job_id = \rand(); |
| 80 | $extension = \pathinfo($file, \PATHINFO_EXTENSION); |
| 81 | $job_file = Str::finish(\dirname($file), \DIRECTORY_SEPARATOR) . "iawp-click-data-{$job_id}.{$extension}"; |
| 82 | $was_renamed = \rename($file, $job_file); |
| 83 | if (!$was_renamed || !\is_file($job_file)) { |
| 84 | return null; |
| 85 | } |
| 86 | return $job_file; |
| 87 | } |
| 88 | } |
| 89 |