/**
  * @param TypeInterface $type
  */
 public function buildType(TypeInterface $type)
 {
     $base_manager_class_name = Inflector::classify($type->getName());
     $type_class_name = Inflector::classify(Inflector::singularize($type->getName()));
     $base_class_build_path = $this->getBuildPath() ? "{$this->getBuildPath()}/Manager/Base/{$base_manager_class_name}.php" : null;
     $result = [];
     $result[] = '<?php';
     $result[] = '';
     if ($this->getStructure()->getConfig('header_comment')) {
         $result = array_merge($result, explode("\n", $this->getStructure()->getConfig('header_comment')));
         $result[] = '';
     }
     if ($this->getStructure()->getNamespace()) {
         $base_class_namespace = $this->getStructure()->getNamespace() . '\\Manager\\Base';
         $type_class_name = '\\' . ltrim($this->getStructure()->getNamespace(), '\\') . '\\' . $type_class_name;
     } else {
         $base_class_namespace = 'Manager\\Base';
     }
     $result[] = 'namespace ' . $base_class_namespace . ';';
     $result[] = '';
     $result[] = '/**';
     $result[] = ' * @package ' . $base_class_namespace;
     $result[] = ' */';
     $interfaces = $traits = [];
     foreach ($type->getTraits() as $interface => $implementations) {
         if ($interface != '--just-paste-trait--') {
             $interfaces[] = '\\' . ltrim($interface, '\\');
         }
         if (count($implementations)) {
             foreach ($implementations as $implementation) {
                 $traits[] = '\\' . ltrim($implementation, '\\');
             }
         }
     }
     $result[] = 'abstract class ' . $base_manager_class_name . ' extends \\ActiveCollab\\DatabaseObject\\Entity\\Manager';
     $result[] = '{';
     $result[] = '    /**';
     $result[] = '     * Return type that this manager works with.';
     $result[] = '     *';
     $result[] = '     * @return string';
     $result[] = '     */';
     $result[] = '    public function getType()';
     $result[] = '    {';
     $result[] = '        return ' . var_export($type_class_name, true) . ';';
     $result[] = '    }';
     $result[] = '}';
     $result[] = '';
     $result = implode("\n", $result);
     if ($this->getBuildPath()) {
         file_put_contents($base_class_build_path, $result);
     } else {
         eval(ltrim($result, '<?php'));
     }
     $this->triggerEvent('on_class_built', [$base_manager_class_name, $base_class_build_path]);
 }
 /**
  * @param TypeInterface $type
  */
 public function buildType(TypeInterface $type)
 {
     $base_class_name = Inflector::classify(Inflector::singularize($type->getName()));
     $base_class_extends = '\\' . ltrim($type->getBaseClassExtends(), '\\');
     $base_class_build_path = $this->getBuildPath() ? "{$this->getBuildPath()}/Base/{$base_class_name}.php" : null;
     $result = [];
     $result[] = '<?php';
     $result[] = '';
     if ($this->getStructure()->getConfig('header_comment')) {
         $result = array_merge($result, explode("\n", $this->getStructure()->getConfig('header_comment')));
         $result[] = '';
     }
     $base_class_namespace = $this->getStructure()->getNamespace() ? $this->getStructure()->getNamespace() . '\\Base' : 'Base';
     $result[] = 'namespace ' . $base_class_namespace . ';';
     $result[] = '';
     $result[] = '/**';
     $this->buildBaseClassDocBlockProperties('', $result);
     $result[] = ' * @package ' . $base_class_namespace;
     $result[] = ' */';
     $interfaces = $traits = [];
     foreach ($type->getTraits() as $interface => $implementations) {
         if ($interface != '--just-paste-trait--') {
             $interfaces[] = '\\' . ltrim($interface, '\\');
         }
         if (count($implementations)) {
             foreach ($implementations as $implementation) {
                 $traits[] = '\\' . ltrim($implementation, '\\');
             }
         }
     }
     $result[] = 'abstract class ' . $base_class_name . ' extends ' . $base_class_extends . (empty($interfaces) ? '' : ' implements ' . implode(', ', $interfaces));
     $result[] = '{';
     if (count($traits)) {
         $trait_tweaks_count = count($type->getTraitTweaks());
         $result[] = '    use ' . implode(', ', $traits) . ($trait_tweaks_count ? '{' : ';');
         if ($trait_tweaks_count) {
             for ($i = 0; $i < $trait_tweaks_count - 1; ++$i) {
                 $result[] = '        ' . $type->getTraitTweaks()[$i] . ($i < $trait_tweaks_count - 2 ? ',' : '');
             }
             $result[] = '    }';
         }
         $result[] = '';
     }
     $result[] = '    /**';
     $result[] = '     * Name of the table where records are stored.';
     $result[] = '     *';
     $result[] = '     * @var string';
     $result[] = '     */';
     $result[] = '    protected $table_name = ' . var_export($type->getTableName(), true) . ';';
     $fields = $type->getAllFields();
     $this->buildFields($fields, '    ', $result);
     $this->buildGeneratedFields(array_keys($type->getGeneratedFields()), '    ', $result);
     if (count($type->getProtectedFields())) {
         $result[] = '';
         $result[] = '    /**';
         $result[] = '     * List of protected fields.';
         $result[] = '     *';
         $result[] = '     * @var array';
         $result[] = '     */';
         $result[] = '    protected $protected_fields = [' . implode(', ', array_map(function ($field) {
             return var_export($field, true);
         }, $type->getProtectedFields())) . '];';
     }
     if ($type->getOrderBy() != ['id']) {
         $result[] = '';
         $result[] = '    /**';
         $result[] = '     * @var string[]';
         $result[] = '     */';
         $result[] = '    protected $order_by = [' . implode(', ', array_map(function ($value) {
             return var_export($value, true);
         }, $type->getOrderBy())) . '];';
     }
     $this->buildConfigureMethod($type->getGeneratedFields(), '    ', $result);
     foreach ($type->getAssociations() as $association) {
         $association->buildClassMethods($this->getStructure(), $type, $this->getStructure()->getType($association->getTargetTypeName()), $result);
     }
     foreach ($fields as $field) {
         if ($field instanceof ScalarField && $field->getShouldBeAddedToModel() && $field->getName() != 'id') {
             $this->buildFieldGetterAndSetter($field, '    ', $result);
         }
     }
     foreach ($type->getGeneratedFields() as $field_name => $caster) {
         $this->buildGeneratedFieldGetter($field_name, $caster, '    ', $result);
     }
     $build_custom_get_field_value = false;
     foreach ($fields as $field) {
         if ($field instanceof ScalarField && $field->getShouldBeAddedToModel() && !empty($field->getDeserializingCode('raw_value'))) {
             $build_custom_get_field_value = true;
             break;
         }
     }
     if ($build_custom_get_field_value) {
         $result[] = '';
         $result[] = '    /**';
         $result[] = '     * {@inheritdoc}';
         $result[] = '     */';
         $result[] = '    public function getFieldValue($field, $default = null)';
         $result[] = '    {';
         $result[] = '        $value = parent::getFieldValue($field, $default);';
         $result[] = '';
         $result[] = '        if ($value === null) {';
         $result[] = '            return null;';
         $result[] = '        } else {';
         $result[] = '            switch ($field) {';
         foreach ($fields as $field) {
             if ($field instanceof ScalarField && $field->getShouldBeAddedToModel() && !empty($field->getDeserializingCode('value'))) {
                 $result[] = '                case ' . var_export($field->getName(), true) . ':';
                 $result[] = '                    return ' . $field->getDeserializingCode('value') . ';';
             }
         }
         $result[] = '            }';
         $result[] = '';
         $result[] = '            return $value;';
         $result[] = '        }';
         $result[] = '    }';
     }
     $result[] = '';
     $result[] = '    /**';
     $result[] = '     * {@inheritdoc}';
     $result[] = '     */';
     $result[] = '    public function &setFieldValue($name, $value)';
     $result[] = '    {';
     $result[] = '        if ($value === null) {';
     $result[] = '            parent::setFieldValue($name, null);';
     $result[] = '        } else {';
     $result[] = '            switch ($name) {';
     $casters = [];
     foreach ($fields as $field) {
         if ($field instanceof ScalarField && $field->getShouldBeAddedToModel()) {
             $casting_code = $field->getCastingCode('value');
             if (empty($casters[$casting_code])) {
                 $casters[$casting_code] = [];
             }
             $casters[$casting_code][] = $field->getName();
         }
     }
     foreach ($casters as $caster_code => $casted_field_names) {
         foreach ($casted_field_names as $casted_field_name) {
             $result[] = '                case ' . var_export($casted_field_name, true) . ':';
         }
         $result[] = '                    return parent::setFieldValue($name, ' . $caster_code . ');';
     }
     $result[] = '                default:';
     $result[] = '                    if ($this->isLoading()) {';
     $result[] = '                        return parent::setFieldValue($name, $value);';
     $result[] = '                    } else {';
     $result[] = '                        if ($this->isGeneratedField($name)) {';
     $result[] = '                            throw new \\LogicException("Generated field $name cannot be set by directly assigning a value");';
     $result[] = '                        } else {';
     $result[] = '                            throw new \\InvalidArgumentException("Field $name does not exist in this table");';
     $result[] = '                        }';
     $result[] = '                    }';
     $result[] = '            }';
     $result[] = '        }';
     $result[] = '';
     $result[] = '        return $this;';
     $result[] = '    }';
     $this->buildJsonSerialize($type->getSerialize(), '    ', $result);
     $this->buildCompositeFieldMethods($type->getFields(), '    ', $result);
     $this->buildValidate($type->getFields(), $type->getAssociations(), '    ', $result);
     $result[] = '}';
     $result[] = '';
     $result = implode("\n", $result);
     if ($this->getBuildPath()) {
         file_put_contents($base_class_build_path, $result);
     } else {
         eval(ltrim($result, '<?php'));
     }
     $this->triggerEvent('on_class_built', [$base_class_name, $base_class_build_path]);
 }