public function exportGettableProperties(array $propertyNameMap = array(), $onlyMappedProperties = false)
    {
        $export = array();
        $propertyNameMap = $this->convertPropertyMap($propertyNameMap);

        // Loop values, skipping mapped properties, use Trait's internal getter to get value.
        // We are suppressing Exceptions in this step in order to not disclose the reason why
        // a particular property could not be read. Possible causes are visibility, typos
        // in getter method name, non-standard getter method naming, or third-party Exceptions
        // being thrown from a getter.
        if (!$onlyMappedProperties) {
            $sourcePropertyNames = array_keys(get_class_vars(get_called_class()));
            foreach ($sourcePropertyNames as $propertyName) {
                if (isset($propertyNameMap[$propertyName]) || $propertyName === 'populatableAccessorMethodNames') {
                    continue;
                }
                try {
                    $export[$propertyName] = $this->getPopulatedProperty($propertyName);
                } catch (Exception $error) {
                    // @TODO: consider logging failures w/ reason
                    continue;
                }
            }
        }

        // loop the mapped properties last to ensure mapping overrides defaults
        foreach ($propertyNameMap as $sourcePropertyName => $targetPropertyName) {
            $export[$targetPropertyName] = $this->getPopulatedProperty($sourcePropertyName);
        }

        return $export;
    }