98 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
		
		
			
		
	
	
			98 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| 
								 | 
							
								<?php
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace SparkPlug\Com\Noccy\Watcher\Monitor;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								use SparkPlug\Com\Noccy\Watcher\Rule;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class InotifyMonitor implements MonitorInterface
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    private array $rules = [];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    private array $watched = [];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    private array $modified = [];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    private $fd;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    public function __construct()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $this->fd = \inotify_init();   
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    public function __destruct()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if (is_resource($this->fd)) fclose($this->fd);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * {@inheritDoc}
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function add(Rule $rule)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $this->rules[] = $rule;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $paths = $rule->getWatchedFiles();
							 | 
						||
| 
								 | 
							
								        $check = [];
							 | 
						||
| 
								 | 
							
								        foreach ($paths as $path) {
							 | 
						||
| 
								 | 
							
								            if (str_contains($path, '*')) {
							 | 
						||
| 
								 | 
							
								                $check = array_merge($check, glob($path));
							 | 
						||
| 
								 | 
							
								            } else {
							 | 
						||
| 
								 | 
							
								                $check[] = $path;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        $dirs = [];
							 | 
						||
| 
								 | 
							
								        foreach ($check as $path) {
							 | 
						||
| 
								 | 
							
								            $dir = is_dir($path) ? $path : dirname($path);
							 | 
						||
| 
								 | 
							
								            if (!array_key_exists($dir, $dirs)) {
							 | 
						||
| 
								 | 
							
								                $dirs[$dir] = $rule;
							 | 
						||
| 
								 | 
							
								                \inotify_add_watch($this->fd, $dir, \IN_ATTRIB);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        $this->watched = array_merge($this->watched, $dirs);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * {@inheritDoc}
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function getModified(): array
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $mod = $this->modified;
							 | 
						||
| 
								 | 
							
								        $this->modified = [];
							 | 
						||
| 
								 | 
							
								        return $mod;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * {@inheritDoc}
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function getWatched(): array
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return [];        
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    public function loop()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $read = [ $this->fd ];
							 | 
						||
| 
								 | 
							
								        $write = null;
							 | 
						||
| 
								 | 
							
								        $except = null;
							 | 
						||
| 
								 | 
							
								        $changed = [];
							 | 
						||
| 
								 | 
							
								        while (stream_select($read,$write,$except,0)) {
							 | 
						||
| 
								 | 
							
								            $events = \inotify_read($this->fd);
							 | 
						||
| 
								 | 
							
								            foreach ($events as $event) {
							 | 
						||
| 
								 | 
							
								                $changed[] = $event['name'];
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        foreach ($changed as $file) {
							 | 
						||
| 
								 | 
							
								            foreach ($this->watched as $dir=>$rule) {
							 | 
						||
| 
								 | 
							
								                if (file_exists($dir."/".$file)) {
							 | 
						||
| 
								 | 
							
								                    if (!in_array($rule, $this->modified)) {
							 | 
						||
| 
								 | 
							
								                        printf("~ modified: %s (%s)\n", $dir."/".$file, $rule->getName());
							 | 
						||
| 
								 | 
							
								                        $this->modified[] = $rule;
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 |