1<?php 2 3namespace JMS\Serializer; 4 5use JMS\Serializer\Exception\RuntimeException; 6use JMS\Serializer\Metadata\ClassMetadata; 7use JMS\Serializer\Metadata\PropertyMetadata; 8use JMS\Serializer\Naming\AdvancedNamingStrategyInterface; 9use JMS\Serializer\Naming\PropertyNamingStrategyInterface; 10 11/** 12 * Generic Deserialization Visitor. 13 * @deprecated 14 * @author Johannes M. Schmitt <schmittjoh@gmail.com> 15 */ 16abstract class GenericDeserializationVisitor extends AbstractVisitor 17{ 18 private $navigator; 19 private $result; 20 private $objectStack; 21 private $currentObject; 22 23 public function setNavigator(GraphNavigator $navigator) 24 { 25 $this->navigator = $navigator; 26 $this->result = null; 27 $this->objectStack = new \SplStack; 28 } 29 30 public function getNavigator() 31 { 32 return $this->navigator; 33 } 34 35 public function prepare($data) 36 { 37 return $this->decode($data); 38 } 39 40 public function visitNull($data, array $type, Context $context) 41 { 42 return null; 43 } 44 45 public function visitString($data, array $type, Context $context) 46 { 47 $data = (string)$data; 48 49 if (null === $this->result) { 50 $this->result = $data; 51 } 52 53 return $data; 54 } 55 56 public function visitBoolean($data, array $type, Context $context) 57 { 58 $data = (Boolean)$data; 59 60 if (null === $this->result) { 61 $this->result = $data; 62 } 63 64 return $data; 65 } 66 67 public function visitInteger($data, array $type, Context $context) 68 { 69 $data = (integer)$data; 70 71 if (null === $this->result) { 72 $this->result = $data; 73 } 74 75 return $data; 76 } 77 78 public function visitDouble($data, array $type, Context $context) 79 { 80 $data = (double)$data; 81 82 if (null === $this->result) { 83 $this->result = $data; 84 } 85 86 return $data; 87 } 88 89 public function visitArray($data, array $type, Context $context) 90 { 91 if (!\is_array($data)) { 92 throw new RuntimeException(sprintf('Expected array, but got %s: %s', \gettype($data), json_encode($data))); 93 } 94 95 // If no further parameters were given, keys/values are just passed as is. 96 if (!$type['params']) { 97 if (null === $this->result) { 98 $this->result = $data; 99 } 100 101 return $data; 102 } 103 104 switch (\count($type['params'])) { 105 case 1: // Array is a list. 106 $listType = $type['params'][0]; 107 108 $result = array(); 109 if (null === $this->result) { 110 $this->result = &$result; 111 } 112 113 foreach ($data as $v) { 114 $result[] = $this->navigator->accept($v, $listType, $context); 115 } 116 117 return $result; 118 119 case 2: // Array is a map. 120 list($keyType, $entryType) = $type['params']; 121 122 $result = array(); 123 if (null === $this->result) { 124 $this->result = &$result; 125 } 126 127 foreach ($data as $k => $v) { 128 $result[$this->navigator->accept($k, $keyType, $context)] = $this->navigator->accept($v, $entryType, $context); 129 } 130 131 return $result; 132 133 default: 134 throw new RuntimeException(sprintf('Array type cannot have more than 2 parameters, but got %s.', json_encode($type['params']))); 135 } 136 } 137 138 public function startVisitingObject(ClassMetadata $metadata, $object, array $type, Context $context) 139 { 140 $this->setCurrentObject($object); 141 142 if (null === $this->result) { 143 $this->result = $this->currentObject; 144 } 145 } 146 147 public function visitProperty(PropertyMetadata $metadata, $data, Context $context) 148 { 149 if ($this->namingStrategy instanceof AdvancedNamingStrategyInterface) { 150 $name = $this->namingStrategy->getPropertyName($metadata, $context); 151 } else { 152 $name = $this->namingStrategy->translateName($metadata); 153 } 154 155 if (null === $data) { 156 return; 157 } 158 159 if (!\is_array($data)) { 160 throw new RuntimeException(sprintf('Invalid data "%s"(%s), expected "%s".', $data, $metadata->type['name'], $metadata->reflection->class)); 161 } 162 163 if (!array_key_exists($name, $data)) { 164 return; 165 } 166 167 if (!$metadata->type) { 168 throw new RuntimeException(sprintf('You must define a type for %s::$%s.', $metadata->reflection->class, $metadata->name)); 169 } 170 171 $v = $data[$name] !== null ? $this->navigator->accept($data[$name], $metadata->type, $context) : null; 172 173 $this->accessor->setValue($this->currentObject, $v, $metadata); 174 175 } 176 177 public function endVisitingObject(ClassMetadata $metadata, $data, array $type, Context $context) 178 { 179 $obj = $this->currentObject; 180 $this->revertCurrentObject(); 181 182 return $obj; 183 } 184 185 public function getResult() 186 { 187 return $this->result; 188 } 189 190 public function setCurrentObject($object) 191 { 192 $this->objectStack->push($this->currentObject); 193 $this->currentObject = $object; 194 } 195 196 public function getCurrentObject() 197 { 198 return $this->currentObject; 199 } 200 201 public function revertCurrentObject() 202 { 203 return $this->currentObject = $this->objectStack->pop(); 204 } 205 206 abstract protected function decode($str); 207} 208