Differences Between: [Versions 310 and 311] [Versions 39 and 311]
1 <?php 2 /** 3 * LICENSE 4 * 5 * This file is part of CFPropertyList. 6 * 7 * The PHP implementation of Apple's PropertyList can handle XML PropertyLists 8 * as well as binary PropertyLists. It offers functionality to easily convert 9 * data between worlds, e.g. recalculating timestamps from unix epoch to apple 10 * epoch and vice versa. A feature to automagically create (guess) the plist 11 * structure from a normal PHP data structure will help you dump your data to 12 * plist in no time. 13 * 14 * Copyright (c) 2018 Teclib' 15 * 16 * Permission is hereby granted, free of charge, to any person obtaining a copy 17 * of this software and associated documentation files (the "Software"), to deal 18 * in the Software without restriction, including without limitation the rights 19 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 20 * copies of the Software, and to permit persons to whom the Software is 21 * furnished to do so, subject to the following conditions: 22 * 23 * The above copyright notice and this permission notice shall be included in all 24 * copies or substantial portions of the Software. 25 * 26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 27 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 28 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 29 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 30 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 31 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32 * SOFTWARE. 33 * 34 * ------------------------------------------------------------------------------ 35 * @author Rodney Rehm <rodney.rehm@medialize.de> 36 * @author Christian Kruse <cjk@wwwtech.de> 37 * @copyright Copyright © 2018 Teclib 38 * @package plist 39 * @license MIT 40 * @link https://github.com/TECLIB/CFPropertyList/ 41 * @link http://developer.apple.com/documentation/Darwin/Reference/ManPages/man5/plist.5.html Property Lists 42 * ------------------------------------------------------------------------------ 43 */ 44 45 namespace CFPropertyList; 46 47 use DateTime; 48 use Iterator; 49 use stdClass; 50 51 /** 52 * CFTypeDetector 53 * Interface for converting native PHP data structures to CFPropertyList objects. 54 * @author Rodney Rehm <rodney.rehm@medialize.de> 55 * @author Christian Kruse <cjk@wwwtech.de> 56 * @package plist 57 * @subpackage plist.types 58 * @example example-create-02.php Using CFTypeDetector 59 * @example example-create-03.php Using CFTypeDetector with CFDate and CFData 60 * @example example-create-04.php Using and extended CFTypeDetector 61 */ 62 class CFTypeDetector 63 { 64 65 /** 66 * flag stating if all arrays should automatically be converted to CFDictionary 67 * @var boolean 68 */ 69 protected $autoDictionary = false; 70 71 /** 72 * flag stating if exceptions should be suppressed or thrown 73 * @var boolean 74 */ 75 protected $suppressExceptions = false; 76 77 /** 78 * name of a method that will be used for array to object conversations 79 * @var callable 80 */ 81 protected $objectToArrayMethod = null; 82 83 /** 84 * flag stating if "123.23" should be converted to float (true) or preserved as string (false) 85 * @var boolean 86 */ 87 protected $castNumericStrings = true; 88 89 90 /** 91 * Create new CFTypeDetector 92 * @param array $options Configuration for casting values [autoDictionary, suppressExceptions, objectToArrayMethod, castNumericStrings] 93 */ 94 public function __construct(array $options = array()) 95 { 96 //$autoDicitionary=false,$suppressExceptions=false,$objectToArrayMethod=null 97 foreach ($options as $key => $value) { 98 if (property_exists($this, $key)) { 99 $this->$key = $value; 100 } 101 } 102 } 103 104 /** 105 * Determine if an array is associative or numerical. 106 * Numerical Arrays have incrementing index-numbers that don't contain gaps. 107 * @param array $value Array to check indexes of 108 * @return boolean true if array is associative, false if array has numeric indexes 109 */ 110 protected function isAssociativeArray($value) 111 { 112 $numericKeys = true; 113 $i = 0; 114 foreach ($value as $key => $v) { 115 if ($i !== $key) { 116 $numericKeys = false; 117 break; 118 } 119 $i++; 120 } 121 return !$numericKeys; 122 } 123 124 /** 125 * Get the default value 126 * @return CFType the default value to return if no suitable type could be determined 127 */ 128 protected function defaultValue() 129 { 130 return new CFString(); 131 } 132 133 /** 134 * Create CFType-structure by guessing the data-types. 135 * CFArray, {@link CFDictionary}, {@link CFBoolean}, {@link CFNumber} and {@link CFString} can be created, {@link CFDate} and {@link CFData} cannot. 136 * <br /><b>Note:</b>Distinguishing between {@link CFArray} and {@link CFDictionary} is done by examining the keys. 137 * Keys must be strictly incrementing integers to evaluate to a {@link CFArray}. 138 * Since PHP does not offer a function to test for associative arrays, 139 * this test causes the input array to be walked twice and thus work rather slow on large collections. 140 * If you work with large arrays and can live with all arrays evaluating to {@link CFDictionary}, 141 * feel free to set the appropriate flag. 142 * <br /><b>Note:</b> If $value is an instance of CFType it is simply returned. 143 * <br /><b>Note:</b> If $value is neither a CFType, array, numeric, boolean nor string, it is omitted. 144 * @param mixed $value Value to convert to CFType 145 * @return CFType CFType based on guessed type 146 * @uses isAssociativeArray() to check if an array only has numeric indexes 147 */ 148 public function toCFType($value) 149 { 150 switch (true) { 151 case $value instanceof CFType: 152 return $value; 153 break; 154 155 case is_object($value): 156 // DateTime should be CFDate 157 if ($value instanceof DateTime) { 158 return new CFDate($value->getTimestamp()); 159 } 160 161 // convert possible objects to arrays, arrays will be arrays 162 if ($this->objectToArrayMethod && is_callable(array($value, $this->objectToArrayMethod))) { 163 $value = call_user_func(array( $value, $this->objectToArrayMethod )); 164 } else if ($value instanceof stdClass) { 165 $value = (array) $value; 166 } 167 168 if (!is_array($value)) { 169 if ($this->suppressExceptions) { 170 return $this->defaultValue(); 171 } 172 173 throw new PListException('Could not determine CFType for object of type '. get_class($value)); 174 } 175 /* break; omitted */ 176 177 case $value instanceof Iterator: 178 case is_array($value): 179 // test if $value is simple or associative array 180 if (!$this->autoDictionary) { 181 if (!$this->isAssociativeArray($value)) { 182 $t = new CFArray(); 183 foreach ($value as $v) { 184 $t->add($this->toCFType($v)); 185 } 186 return $t; 187 } 188 } 189 190 $t = new CFDictionary(); 191 foreach ($value as $k => $v) { 192 $t->add($k, $this->toCFType($v)); 193 } 194 195 return $t; 196 break; 197 198 case is_bool($value): 199 return new CFBoolean($value); 200 break; 201 202 case is_null($value): 203 return new CFString(); 204 break; 205 206 case is_resource($value): 207 if ($this->suppressExceptions) { 208 return $this->defaultValue(); 209 } 210 211 throw new PListException('Could not determine CFType for resource of type '. get_resource_type($value)); 212 break; 213 214 case is_numeric($value): 215 if (!$this->castNumericStrings && is_string($value)) { 216 return new CFString($value); 217 } 218 219 return new CFNumber($value); 220 break; 221 222 case is_string($value): 223 if (strpos($value, "\x00") !== false) { 224 return new CFData($value); 225 } 226 return new CFString($value); 227 228 break; 229 230 default: 231 if ($this->suppressExceptions) { 232 return $this->defaultValue(); 233 } 234 235 throw new PListException('Could not determine CFType for '. gettype($value)); 236 break; 237 } 238 } 239 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body