7

I'm trying to figure out how shipment tracking data is stored. Especially when it's set by the API. So when I look at sales/etc/webapi.xml I see the following.

<route url="/V1/shipment/track" method="POST">
    <service class="Magento\Sales\Api\ShipmentTrackRepositoryInterface" method="save"/>
    <resources>
        <resource ref="Magento_Sales::sales" />
    </resources>
</route>

This leads me to sales/etc/di.xml where I see the following:

<preference for="Magento\Sales\Api\ShipmentTrackRepositoryInterface" 
            type="Magento\Sales\Api\Data\ShipmentTrack\Repository"/>

Now this is where my question starts. Because I can't seem to find a class named Magento\Sales\Api\Data\ShipmentTrack\Repository. Or am I missing something here?

  • See {magento-root-dir}/var/generation/Magento/Sales/Api/Data/ShipmentTrack.php – Willem-Jan Dec 6 '16 at 14:56
  • @GielBerkers, did you ever solve this? Has the above comment helped you out? – 7ochem Jan 17 '17 at 10:20
  • I guess so. It's just... I know code generation is responsible for Factories and Interceptors. But are repositories generated as well? It doesn't state so in the documentation. Is there anywhere a comprehensive guide about what kind of objects are generated by Magentos' code generating mechanism? – Giel Berkers Feb 9 '17 at 12:51
2

You can find the Magento 2 generation logic here, especialy for repositories :

If the class is missing, Magento will try to generate it

For your case here : {magento-root-dir}/var/generation/Magento/Sales/Api/Data/Shi‌​pmentTrack.php

vendor/magento/magento2-base/app/etc/di.xml

<type name="Magento\Framework\Code\Generator">
    <arguments>
        <argument name="generatedEntities" xsi:type="array">
            <item name="factory" xsi:type="string">\Magento\Framework\ObjectManager\Code\Generator\Factory</item>
            <item name="proxy" xsi:type="string">\Magento\Framework\ObjectManager\Code\Generator\Proxy</item>
            <item name="interceptor" xsi:type="string">\Magento\Framework\Interception\Code\Generator\Interceptor</item>
            <item name="logger" xsi:type="string">\Magento\Framework\ObjectManager\Profiler\Code\Generator\Logger</item>
            <item name="mapper" xsi:type="string">\Magento\Framework\Api\Code\Generator\Mapper</item>
            <item name="persistor" xsi:type="string">\Magento\Framework\ObjectManager\Code\Generator\Persistor</item>
            <item name="repository" xsi:type="string">\Magento\Framework\ObjectManager\Code\Generator\Repository</item>
            <item name="convertor" xsi:type="string">\Magento\Framework\ObjectManager\Code\Generator\Converter</item>
            <item name="searchResults" xsi:type="string">\Magento\Framework\Api\Code\Generator\SearchResults</item>
            <item name="extensionInterface" xsi:type="string">\Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceGenerator</item>
            <item name="extension" xsi:type="string">\Magento\Framework\Api\Code\Generator\ExtensionAttributesGenerator</item>
        </argument>
    </arguments>
</type>

vendor/magento/framework/ObjectManager/Code/Generator/Repository.php

<?php
/**
 * Copyright © 2016 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */

// @codingStandardsIgnoreFile

namespace Magento\Framework\ObjectManager\Code\Generator;

/**
 * Class Repository
 */
class Repository extends \Magento\Framework\Code\Generator\EntityAbstract
{
    /**
     * Entity type
     */
    const ENTITY_TYPE = 'repository';

    /**
     * No Such Entity Exception
     */
    const NO_SUCH_ENTITY_EXCEPTION = '\\Magento\Framework\Exception\NoSuchEntityException';
    const INPUT_EXCEPTION = '\\Magento\Framework\Exception\InputException';
    const SEARCH_CRITERIA = '\\Magento\Framework\Api\SearchCriteria';

    /**
     * Retrieve class properties
     *
     * @return array
     */
    protected function _getClassProperties()
    {
        $properties = [
            [
                'name' => $this->_getSourcePersistorPropertyName(),
                'visibility' => 'protected',
                'docblock' => [
                    'shortDescription' => $this->_getSourcePersistorPropertyName(),
                    'tags' => [
                        [
                            'name' => 'var',
                            'description' => $this->_getPersistorClassName(),
                        ],
                    ],
                ],
            ],
            [
                'name' => $this->_getSourceCollectionFactoryPropertyName(),
                'visibility' => 'protected',
                'docblock' => [
                    'shortDescription' => 'Collection Factory',
                    'tags' => [
                        [
                            'name' => 'var',
                            'description' => $this->_getCollectionFactoryClassName(),
                        ],
                    ],
                ]
            ],
            [
                'name' => 'registry',
                'visibility' => 'protected',
                'defaultValue' => [],
                'docblock' => [
                    'shortDescription' => $this->getSourceClassName() . '[]',
                    'tags' => [
                        [
                            'name' => 'var',
                            'description' => 'array',
                        ],
                    ],
                ]
            ],
            [
                'name' => 'extensionAttributesJoinProcessor',
                'visibility' => 'protected',
                'docblock' => [
                    'shortDescription' => 'Extension attributes join processor.',
                    'tags' => [
                        [
                            'name' => 'var',
                            'description' => '\Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface',
                        ],
                    ],
                ]
            ],
        ];
        return $properties;
    }

    /**
     * Returns source factory property name
     *
     * @return string
     */
    protected function _getSourcePersistorPropertyName()
    {
        return lcfirst($this->getSourceClassNameWithoutNamespace()) . 'Persistor';
    }

    /**
     * Returns source collection factory property name
     * @return string
     */
    protected function _getSourceCollectionFactoryPropertyName()
    {
        return lcfirst($this->getSourceClassNameWithoutNamespace()) . 'SearchResultFactory';
    }

    /**
     * Returns collection factory class name
     *
     * @return string
     */
    protected function _getCollectionFactoryClassName()
    {
        return
            str_replace('Interface', '', $this->getSourceClassName()) . 'SearchResultInterfaceFactory';
    }
    /**
     * Returns source persistor class name
     *
     * @return string
     */
    protected function _getPersistorClassName()
    {
        $target = $this->getSourceClassName();
//        if (substr($target, -9) == 'Interface') {
//            $target = substr($target, 1, strlen($target) -9);
//        }
        return $target . 'Persistor';
    }

    /**
     * Get default constructor definition for generated class
     *
     * @return array
     */
    protected function _getDefaultConstructorDefinition()
    {
        return [
            'name' => '__construct',
            'parameters' => [
                [
                    'name' => $this->_getSourcePersistorPropertyName(),
                    'type' => $this->_getPersistorClassName(),
                ],
                [
                    'name' => $this->_getSourceCollectionFactoryPropertyName(),
                    'type' => $this->_getCollectionFactoryClassName(),
                ],
                [
                    'name' => 'extensionAttributesJoinProcessor',
                    'type' => '\Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface',
                ],
            ],
            'body' => "\$this->"
                . $this->_getSourcePersistorPropertyName()
                . " = \$" . $this->_getSourcePersistorPropertyName() . ";\n"
                . "\$this->"
                . $this->_getSourceCollectionFactoryPropertyName()
                . " = \$" . $this->_getSourceCollectionFactoryPropertyName() . ";\n"
                . "\$this->extensionAttributesJoinProcessor = \$extensionAttributesJoinProcessor;"
            ,
            'docblock' => [
                'shortDescription' => ucfirst(static::ENTITY_TYPE) . ' constructor',
                'tags' => [
                    [
                        'name' => 'param',
                        'description' => $this->getSourceClassName() . " \$" . $this->_getSourcePersistorPropertyName(),
                    ],
                    [
                        'name' => 'param',
                        'description' => $this->_getCollectionFactoryClassName()
                            . " \$" . $this->_getSourceCollectionFactoryPropertyName()
                    ],
                    [
                        'name' => 'param',
                        'description' => '\Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface'
                            . " \$extensionAttributesJoinProcessor"
                    ],
                ],
            ]
        ];
    }

    /**
     * Returns get() method
     *
     * @return string
     */
    protected function _getGetMethod()
    {
        $body = "if (!\$id) {\n"
            . "    throw new " . self::INPUT_EXCEPTION . "('ID required');\n"
            . "}\n"
            . "if (!isset(\$this->registry[\$id])) {\n"
            . "    \$entity = \$this->" . $this->_getSourcePersistorPropertyName()
            . "->loadEntity(\$id);\n"
            . "    if (!\$entity->getId()) {\n"
            . "        throw new " . self::NO_SUCH_ENTITY_EXCEPTION . "('Requested entity doesn\\'t exist');\n"
            . "    }\n"
            . "    \$this->registry[\$id] = \$entity;\n"
            . "}\n"
            . "return \$this->registry[\$id];";
        return [
            'name' => 'get',
            'parameters' => [
                [
                    'name' => 'id',
                    'type' => 'int',
                ],
            ],
            'body' => $body,
            'docblock' => [
                'shortDescription' => 'load entity',
                'tags' => [
                    [
                        'name' => 'param',
                        'description' => 'int $id',
                    ],
                    [
                        'name' => 'return',
                        'description' => $this->getSourceClassName(),
                    ],
                    [
                        'name' => 'throws',
                        'description' => self::INPUT_EXCEPTION,
                    ],
                    [
                        'name' => 'throws',
                        'description' => self::NO_SUCH_ENTITY_EXCEPTION,
                    ],
                ],
            ]
        ];
    }

    /**
     * Returns register() method
     *
     * @return string
     */
    protected function _getCreateFromArrayMethod()
    {
        $body = "return \$this->{$this->_getSourcePersistorPropertyName()}->registerFromArray(\$data);";
        return [
            'name' => 'createFromArray',
            'parameters' => [
                [
                    'name' => 'data',
                    'type' => 'array',
                ],
            ],
            'body' => $body,
            'docblock' => [
                'shortDescription' => 'Register entity to create',
                'tags' => [
                    [
                        'name' => 'param',
                        'description' => 'array $data',
                    ],
                    [
                        'name' => 'return',
                        'description' => $this->_getResultClassName(),
                    ],
                ],
            ]
        ];
    }

    /**
     * Returns register() method
     *
     * @return string
     */
    protected function _getCreateMethod()
    {
        $body = "return \$this->{$this->_getSourcePersistorPropertyName()}->registerNew(\$entity);";
        return [
            'name' => 'create',
            'parameters' => [
                [
                    'name' => 'entity',
                    'type' => $this->getSourceClassName(),
                ],
            ],
            'body' => $body,
            'docblock' => [
                'shortDescription' => 'Register entity to create',
                'tags' => [
                    [
                        'name' => 'param',
                        'description' => 'array $data',
                    ],
                    [
                        'name' => 'return',
                        'description' => $this->getSourceClassName(),
                    ],
                ],
            ]
        ];
    }

    /**
     * Returns register() method
     *
     * @return string
     */
    protected function _getFlushMethod()
    {
        $body = "\$ids = \$this->{$this->_getSourcePersistorPropertyName()}->doPersist();\n"
            . "foreach (\$ids as \$id) {\n"
            . "unset(\$this->registry[\$id]);\n"
            . "}";
        return [
            'name' => 'flush',
            'parameters' => [],
            'body' => $body,
            'docblock' => [
                'shortDescription' => 'Perform persist operations',
                'tags' => [],
            ]
        ];
    }

    /**
     * Returns persist() method
     *
     * @return string
     */
    protected function _getSaveMethod()
    {
        $body = "\$this->{$this->_getSourcePersistorPropertyName()}->doPersistEntity(\$entity);\n"
            . "return \$entity;";
        return [
            'name' => 'save',
            'parameters' => [
                [
                    'name' => 'entity',
                    'type' => $this->getSourceClassName(),
                ],
            ],
            'body' => $body,
            'docblock' => [
                'shortDescription' => 'Perform persist operations for one entity',
                'tags' => [
                    [
                        'name' => 'param',
                        'description' => $this->getSourceClassName() . " \$entity",
                    ],
                    [
                        'name' => 'return',
                        'description' => $this->getSourceClassName(),
                    ],
                ],
            ]
        ];
    }

    /**
     * Return remove() method
     *
     * @return array
     */
    protected function _getDeleteMethod()
    {
        $body = "\$this->{$this->_getSourcePersistorPropertyName()}->registerDeleted(\$entity);\n"
            . "return \$this->{$this->_getSourcePersistorPropertyName()}->doPersistEntity(\$entity);";
        return [
            'name' => 'delete',
            'parameters' => [
                [
                    'name' => 'entity',
                    'type' => $this->getSourceClassName(),
                ],
            ],
            'body' => $body,
            'docblock' => [
                'shortDescription' => 'Register entity to delete',
                'tags' => [
                    [
                        'name' => 'param',
                        'description' => $this->getSourceClassName() . ' $entity',
                    ],
                    [
                        'name' => 'return',
                        'description' => 'bool',
                    ],
                ],
            ]
        ];
    }

    /**
     * Return remove() method
     *
     * @return array
     */
    protected function _getDeleteByIdMethod()
    {
        $body = "\$entity = \$this->get(\$id);\n"
            . "\$this->{$this->_getSourcePersistorPropertyName()}->registerDeleted(\$entity);\n"
            . "return \$this->{$this->_getSourcePersistorPropertyName()}->doPersistEntity(\$entity);";
        return [
            'name' => 'deleteById',
            'parameters' => [
                [
                    'name' => 'id',
                    'type' => 'int',
                ],
            ],
            'body' => $body,
            'docblock' => [
                'shortDescription' => 'Delete entity by Id',
                'tags' => [
                    [
                        'name' => 'param',
                        'description' => 'int $id',
                    ],
                    [
                        'name' => 'return',
                        'description' => 'bool',
                    ],
                ],
            ]
        ];
    }

    /**
     * Return remove() method
     *
     * @return array
     */
    protected function _getRemoveMethod()
    {
        $body = "\$this->{$this->_getSourcePersistorPropertyName()}->registerDeleted(\$entity);";
        return [
            'name' => 'remove',
            'parameters' => [
                [
                    'name' => 'entity',
                    'type' => $this->getSourceClassName(),
                ],
            ],
            'body' => $body,
            'docblock' => [
                'shortDescription' => 'Register entity to delete',
                'tags' => [
                    [
                        'name' => 'param',
                        'description' => $this->getSourceClassName() . ' $entity',
                    ],
                ],
            ]
        ];
    }

    /**
     * Returns getList() method
     *
     * @return string
     */
    protected function _getGetListMethod()
    {
        $body = "\$collection = \$this->" . $this->_getSourceCollectionFactoryPropertyName() . "->create();\n"
        . "\$this->extensionAttributesJoinProcessor->process(\$collection);\n"
        . "foreach (\$searchCriteria->getFilterGroups() as \$filterGroup) {\n"
        . "    foreach (\$filterGroup->getFilters() as \$filter) {\n"
        . "        \$condition = \$filter->getConditionType() ? \$filter->getConditionType() : 'eq';\n"
        . "        \$collection->addFieldToFilter(\$filter->getField(), [\$condition => \$filter->getValue()]);\n"
        . "    }\n"
        . "}\n"
        . "\$collection->setCurPage(\$searchCriteria->getCurrentPage());\n"
        . "\$collection->setPageSize(\$searchCriteria->getPageSize());\n"
        . "return \$collection;\n";
        return [
            'name' => 'getList',
            'parameters' => [
                [
                    'name' => 'searchCriteria',
                    'type' => self::SEARCH_CRITERIA,
                ],
            ],
            'body' => $body,
            'docblock' => [
                'shortDescription' => 'Find entities by criteria',
                'tags' => [
                    [
                        'name' => 'param',
                        'description' => self::SEARCH_CRITERIA . ' $searchCriteria',
                    ],
                    [
                        'name' => 'return',
                        'description' => $this->getSourceClassName() . '[]',
                    ],
                ],
            ]
        ];
    }

    /**
     * Returns list of methods for class generator
     *
     * @return array
     */
    protected function _getClassMethods()
    {
        return [
            $this->_getDefaultConstructorDefinition(),
            $this->_getGetMethod(),
            $this->_getCreateMethod(),
            $this->_getCreateFromArrayMethod(),
            $this->_getGetListMethod(),
            $this->_getRemoveMethod(),
            $this->_getDeleteMethod(),
            $this->_getDeleteByIdMethod(),
            $this->_getFlushMethod(),
            $this->_getSaveMethod()
        ];
    }

    /**
     * {@inheritdoc}
     */
    protected function _validateData()
    {
        $result = parent::_validateData();

        if ($result) {
            $sourceClassName = $this->getSourceClassName();
            $resultClassName = $this->_getResultClassName();

            if ($resultClassName !== str_replace('Interface', '', $sourceClassName) . '\\Repository') {
                $this->_addError(
                    'Invalid Factory class name [' . $resultClassName . ']. Use ' . $sourceClassName . 'Repository'
                );
                $result = false;
            }
        }
        return $result;
    }

    /**
     * Generate code
     *
     * @return string
     */
    protected function _generateCode()
    {
        $className = str_replace('Interface', '', str_replace('Data\\', '', $this->getSourceClassName()));
        $this->_classGenerator->setName(
            $this->_getResultClassName()
        )->addProperties(
            $this->_getClassProperties()
        )->addMethods(
            $this->_getClassMethods()
        )->setClassDocBlock(
            $this->_getClassDocBlock()
        )->setImplementedInterfaces(
            [
                $className . 'RepositoryInterface',
            ]
        );
        return $this->_getGeneratedCode();
    }

    /**
     * Get source class name
     *
     * @return string
     */
    public function getSourceClassName()
    {
        return parent::getSourceClassName() . 'Interface';
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.