Migrate TYPO3 Extbase task to Symfony command - symfony

I'm trying to migrate the extension pb_social to TYPO3 10 LTS but I'm stuck in the migration of the scheduler task that updates TYPO3 data from the social feeds.
I learned how to register a Symfony Console Command with the Services.yaml file so I can execute the command.
The problem is that the pb_social extension relies on Extbase same as its actual updateFeedDataCommand command.
So I tried to create a new command in the Symfony style and in its method execute() I instantiated:
$objectManager = GeneralUtility::makeInstance(ObjectManager::class);
/** #var PBSocialCommandController $controller */
$controller = $objectManager->get(PBSocialCommandController::class);
I already updated the properties of pb_social methods to use the new #TYPO3\CMS\Extbase\Annotation\Inject but still the injections seems not to work.
E.g. with:
/**
* #var \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
* #TYPO3\CMS\Extbase\Annotation\Inject
*/
protected $configurationManager;
$this->configurationManager is null when used.
What could be the problem?

Soved using Method Injection
/**
* #param ConfigurationManager $configurationManager
*/
public function injectConfigurationManager(ConfigurationManager $configurationManager)
{
$this->configurationManager = $configurationManager;
}

Related

PhpStorm Symfony routes missing

I have a rather large Symfony 4.4 project that I recently reopened. Going through the code with PhpStorm 2020.3, adding some new functionality and code cleanup.
I get to a couple of Controllers and I'm getting a "Missing Route" error in PhpStorm. However, the routes do exist when I run php bin/console debug:router.
Is there a cache that I haven't cleared to cause PhpStorm to rescan routes?
Output from: php bin/console debug:router
admin_deviceprofile_index GET ANY ANY /admin/deviceprofile/
admin_deviceprofile_show GET ANY ANY /admin/deviceprofile/{deviceprofile_id}/show
admin_deviceprofile_create GET|POST ANY ANY /admin/deviceprofile/create
admin_deviceprofile_edit GET|POST ANY ANY /admin/deviceprofile/{deviceprofile_id}/edit
admin_deviceprofile_delete DELETE ANY ANY /admin/deviceprofile/{deviceprofile_id}/delete
My snippet of the Controller ...
/**
* #Route("/admin/deviceprofile",
* name="admin_deviceprofile_")
*/
class DeviceProfileController extends AbstractController
{
/**
* Lists all Device Profiles.
* #Route("/",
* name="index",
* methods={"GET"})
* #param Request $request
* #return Response
*/
public function index(Request $request): Response
{ ... }
/**
* Creates a new Device Profile entity.
* #Route("/create",
* name="create",
* methods={"GET", "POST"})
* #param Request $request
* #return Response
*/
public function create(Request $request): Response
{
$profile = new DeviceProfile();
$formProfile = $this->createForm(DeviceProfileType::class, $profile);
$formProfile->handleRequest($request);
if ($formProfile->isSubmitted() && $formProfile->isValid()) {
...
return $this->redirectToRoute('admin_deviceprofile_index');
}
return $this->render(...);
}
}
PhpStorm claims the 'admin_deviceprofile_index' is Missing. However, it is not. Also, this same pattern of having a route for the controller is used elsewhere, yet those routes are fine, the problem appears in just a couple of Controllers.
Also, through debugging this 'problem', I moved the controller route partials to the functions themselves, and PhpStorm still did not see the routes properly.
I have also ran php bin/console cache:clear and have done the PhpStorm: File > Invalidate Caches / Restart to no avail.
Anything I could try to clear this up? I loathe seeing "errors" in the code inspection.
Figured out that if you have a PhpStorm #noinspection tag block and a class-level docblock, it will conflict causing the erroneous "Missing Route" message.
Github issue here

Inject repository into phpleague/oauth-server:authServer

I'm currently trying to set up the phpleague/oauth-server in a symfony 3.3 project. For that reason i want to specify the AuthorizationServer as service to be able to load it from the container (an not set up the whole thing everywhere its used).
To set the AuthorizationServer as service I need to inject multiple repositories as arguments.
This is the service definition for the AuthorizationServer:
app.oauth2.authorization_server:
class: League\OAuth2\Server\AuthorizationServer
arguments: ["#app.oauth2.client_repository", "#app.oauth2.access_token_repository", "#app.oauth2.scope_repository", "%oauth_private_key%", "%oauth_encryption_key%"]
configurator: "app.oauth2.authorization_server.configurator:configure"
The current definition of the repositories looks like this:
app.oauth2.client_repository:
class: Appbundle\Repository\OAuth2\ClientRepository
factory: 'doctrine.orm.entity_manager:getRepository'
arguments: [AppBundle\Entity\OAuth2\Client]
...
I tried many ways of defining the repositories as services but everytime i get the same error:
Type error: Argument 1 passed to League\\OAuth2\\Server\\AuthorizationServer::__construct() must be an instance of League\\OAuth2\\Server\\Repositories\\ClientRepositoryInterface, instance of Doctrine\\ORM\\EntityRepository given
This is how the ClientRepository looks like:
<?php
namespace AppBundle\Repository\OAuth2;
use League\OAuth2\Server\Entities\ClientEntityInterface;
use League\OAuth2\Server\Repositories\ClientRepositoryInterface;
class ClientRepository implements ClientRepositoryInterface
{
/**
* Get a client.
*
* #param string $clientIdentifier The client's identifier
* #param string $grantType The grant type used
* #param null|string $clientSecret The client's secret (if sent)
* #param bool $mustValidateSecret If true the client must attempt to validate the secret if the client
* is confidential
*
* #return ClientEntityInterface
*/
public function getClientEntity($clientIdentifier, $grantType, $clientSecret = null, $mustValidateSecret = true)
{
// TODO: Implement getClientEntity() method.
}
}
Here are some other ways i tried to implement it:
https://matthiasnoback.nl/2014/05/inject-a-repository-instead-of-an-entity-manager/
How to configure dependency injection for repository class in symfony 3
Neither of them worked. Has any one of you an idea why the service definition of my repository is not accepted as valid input for the AuthorizationServer?
Yours,
FMK
I had tried to extend the EntityRepository but forgot to define the repository in the Entities. With the repositories extending the entityRepository and the ORM\Entity definition in the Entities it seems to work!

How to get autocompletion for container using phpstorm and symfony2 plugin?

I use phpstorm. When developing a symfony2 application I am used to the symfony2 plugin providing an autocompletion for container services:
[
This offers completion on the returned objects as well.
Is there a way to get the service completion to work when using the container component in a non-symfony PHP project that uses only parts of the symfony2 components, i.e. the container component?
I know that in phpstorm's settings:
Other Settings > Symfony2 Plugins > Container
I could add additonal xml container files, yet I have no clue what it should look like.
How would I create such a file?
For instance, I create a container by:
/**
* #return ContainerBuilder
* #todo Initialize the container on a more reasonable place
*/
private function createServiceContainer()
{
$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(ROOT_PATH . '/config'));
$loader->load('services.yml');
return $container;
}
And my services.yml looks like this:
services:
redis:
class: App\Framework\RedisService
doctrine:
class: DoctrineService
factory: [\App\Database\DoctrineService, getDoctrine]
How could I create a container.xml that would be understood by the symfony2 plugin and offer me the two services redis and doctrine in the container?
That XML file is created by the ContainerBuilderDebugDumpPass compiler pass in the Symfony2 Standard Edition, and you can see that it use the XmlDumper to create the file.
I have created an command:
<?php
namespace App\Command;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ContainerBuilderDebugDumpPass;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
/**
* ContainerRefreshCommand
**/
class ContainerRefreshCommand extends Command
{
/**
* Configures the current command.
*/
protected function configure()
{
$this
->setName('container:refresh')
->setDescription('refreshes the container file for usage with phpstorm');
}
/**
* #param InputInterface $input
* #param OutputInterface $output
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(ROOT_PATH . '/config'));
$loader->load('services.yml');
$container->setParameter('debug.container.dump', ROOT_PATH . '/dev/appDevDebugProjectContainer.xml');
$containerFile = new ContainerBuilderDebugDumpPass();
$containerFile->process($container);
}
}
I have then added the file from my project root:
./dev/appDevDebugProjectContainer.xml
in the container definition.
I then had to change the class name of the doctrine service. It appears to be anything goes there, yet this string is what the symfony2 plugins uses to detect the service.
I then got auto-completion for container services.
One has to note that the class property in services.yml is important as well. Since the object I actually get by container->get('doctrine'), is an instance of an EntityManager I have to define this way to get autocompletion:
doctrine:
class: Doctrine\ORM\EntityManager
factory: [\App\Database\DoctrineService, getDoctrine]

Unable to remove phpstorm background

I'm using phpStorm for my Symfony2 project, And I'm getting this "not found" message probably for all methods. so I have 2 questions.
1) Why phpStorm can't find my methods?
2) How to remove this annoying background from "not found" methods?
Screenshot is here:
Thank you. :)
Often PhpStorm cannot guess the type. You can help it by using typehints:
public function indexAction(Request $request);
phpdocblocks:
/**
* #param Request $request
*
* #return Response
*/
public function indexAction(Request $request) {return new Response('');}
and inline comments:
/* #var \Symfony\Component\Form\Form $form */
$form = $this->createForm(/* ... */);
For Symfony, there's an excelent plugin you can install and very much improve your experience with PhpStorm and the Symfony framework: http://plugins.jetbrains.com/plugin/7219?pr=phpStorm
It supports all bunch of features, including autocompletion of container services.
As for the "annoying background", look into PhpStorm color settings. You can configure pretty much anything in there, including changing the theme if you don't like the default one.

Behat+symfony2 access container parameters set in custom extension

(I'm going to explain situation, incase someone knows of a better way to accomplice what I want to do).
Using Symfony2 + Behat + Symfony2Extension + Mink +
We have an application with multiple urls that will be visited during scenarios.
I do understand that you use the parameters sent in from the FeatureContext __construct method, but what I'm trying to do is set up the urls in the behat.yml file so that we can use them in our custom Context to visit the urls.
Looking at how the extensions work I have setup the dependency injection as follows:
class Extension implements ExtensionInterface
{
/**
* Loads a specific configuration.
*
* #param array $config Extension configuration hash (from behat.yml)
* #param ContainerBuilder $container ContainerBuilder instance
*/
public function load(array $config, ContainerBuilder $container)
{
$container->setParameter('url_one', $config['url_one']);
$container->setParameter('url_two', $config['url_two']);
}
/**
* Setups configuration for current extension.
*
* #param ArrayNodeDefinition $builder
*/
public function getConfig(ArrayNodeDefinition $builder)
{
$builder->
children()->
scalarNode('one_url')->
isRequired()->
end()->
scalarNode('two_url')->
isRequired()->
end()->
end();
}
code continues....
And my behat.yml looks like this:
default:
extensions:
Behat\MinkExtension\Extension:
goutte: ~
selenium2: ~
Behat\Symfony2Extension\Extension: ~
Acme\AcmeExtension\Extension:
url_one: 'http://example1.com'
url_two: 'http:/example2.com'
Now in my FeatureContext.php class I would like to do the following:
$url = $kernel->getContainer()->getParameter('url_one');
But this is not working, it is returning parameters from my Symfony2 application, which is expected since I have symfony2extension enabled. But I can not access the parameters or services from the extension class.
(Please note that if I'm in the Extension class in the load method and I call the parameter I just set it returns it, so I know it is set, but it must be set to a different container?)
First off is this possible? And if so what should I do to make it work.
Many thanks for any help.
Obviously, $kernel->getContainer() returns you container of the Symfony2 app kernel. Those kernel and container are not shared with Behat. Behat has its own container instance, which it uses to manage own services. Which means that extension is setting parameters inside Behat container, but you are attempting to access your app kernel container. That's why you have different results.
Now, the question is, how would you pass some value from your extension to context class. Answer is context initialiser. Check out:
https://github.com/Behat/MinkExtension/blob/master/src/Behat/MinkExtension/services/core.xml#L43-L47
https://github.com/Behat/MinkExtension/blob/master/src/Behat/MinkExtension/Context/Initializer/MinkAwareInitializer.php#L26-L77

Resources