/**
  * @param mixed $data
  * @return mixed[] associative array of properties
  */
 protected function getProperties($data)
 {
     $extractor = new ObjectPropertyExtractor($data);
     // Call __sleep if present
     if (method_exists($data, '__sleep')) {
         $properties = call_user_func([$data, '__sleep']);
     } else {
         $properties = $extractor->getProperties();
     }
     $values = $extractor->getValues($properties);
     // Call __wakeup if present to restore previous state
     if (method_exists($data, '__wakeup')) {
         call_user_func([$data, '__wakeup']);
     }
     return $values;
 }