| 1 |  |  | <?php | 
            
                                                                                                            
                            
            
                                    
            
            
                | 2 |  |  | namespace Maphper\Lib; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 3 |  |  | //Replaces dates in an object graph with \DateTime instances | 
            
                                                                                                            
                            
            
                                    
            
            
                | 4 |  |  | class DateInjector { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 5 |  |  | 	private $processCache; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 6 |  |  | 	private $dateFormats = [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 7 |  |  | 		['Y-m-d H:i:s', 20], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 8 |  |  | 		['Y-m-d', 10], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 9 |  |  | 		['Y-n-d', 9] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 10 |  |  | 	]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 11 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 12 |  |  | 	public function replaceDates($obj, $reset = true) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 13 |  |  | 		//prevent infinite recursion, only process each object once | 
            
                                                                                                            
                            
            
                                    
            
            
                | 14 |  |  | 		if ($this->checkCache($obj, $reset)) return $obj; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 15 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 16 |  |  | 		if ($this->isIterable($obj)) foreach ($obj as &$o) $o = $this->replaceDates($o, false); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 17 |  |  | 		if ($this->isPossiblyDateString($obj)) $obj = $this->tryToGetDateObjFromString($obj); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 18 |  |  | 		return $obj; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 19 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 20 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 21 |  |  |     private function tryToGetDateObjFromString($obj) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 22 |  |  |         try { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 23 |  |  |             $date = new \DateTimeImmutable($obj); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 24 |  |  | 			if ($this->dateMatchesFormats($date, $obj)) $obj = $date; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 25 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 26 |  |  |         catch (\Exception $e) {	//Doesn't need to do anything as the try/catch is working out whether $obj is a date | 
            
                                                                                                            
                            
            
                                    
            
            
                | 27 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 28 |  |  |         return $obj; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 29 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 30 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 31 |  |  | 	private function dateMatchesFormats($date, $str) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 32 |  |  | 		foreach ($this->dateFormats as list($format, $len)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 33 |  |  | 			if ($date->format($format) == substr($str, 0, $len)) return true; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 34 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 35 |  |  | 		return false; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 36 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 37 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 38 |  |  |     private function isIterable($obj) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 39 |  |  |         return is_array($obj) || (is_object($obj) && ($obj instanceof \Iterator)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 40 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 41 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 42 |  |  |     private function isPossiblyDateString($obj) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 43 |  |  |         return is_string($obj) && isset($obj[0]) && is_numeric($obj[0]) && strlen($obj) <= 20; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 44 |  |  |     } | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 45 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 46 |  |  | 	private function checkCache($obj, $reset) { | 
            
                                                                        
                            
            
                                    
            
            
                | 47 |  |  | 		if ($reset) $this->processCache = new \SplObjectStorage(); | 
            
                                                                        
                            
            
                                    
            
            
                | 48 |  |  |         if (!is_object($obj)) return false; | 
            
                                                                        
                            
            
                                    
            
            
                | 49 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 50 |  |  | 		if ($this->processCache->contains($obj)) return $obj; | 
            
                                                                        
                            
            
                                    
            
            
                | 51 |  |  | 		else $this->processCache->attach($obj, true); | 
            
                                                                        
                            
            
                                    
            
            
                | 52 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 53 |  |  | 		return false; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 54 |  |  | 	} | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 55 |  |  | } | 
            
                                                        
            
                                    
            
            
                | 56 |  |  |  |