Skip to content

Instantly share code, notes, and snippets.

@anaelChardan
Created August 8, 2019 08:43
Show Gist options
  • Save anaelChardan/2026e148679feae54aa8b2b228e03482 to your computer and use it in GitHub Desktop.
Save anaelChardan/2026e148679feae54aa8b2b228e03482 to your computer and use it in GitHub Desktop.
#!/usr/bin/php
<?php
define('EXIT_WRONG_USAGE', 127);
define('EXIT_SERVICES_NEVER_USED', 1);
if (!file_exists('src/Kernel.php')) {
die("Please run this command from your Symfony application root.");
}
require 'app/bootstrap.php';
require 'vendor/autoload.php';
use Symfony\Component\Console\Exception\RuntimeException;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Output\ConsoleOutput;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\Config\ConfigCache;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\Reference;
$inputDefinition = new InputDefinition();
$output = new ConsoleOutput();
$input = new ArgvInput($argv);
try {
$input->bind($inputDefinition);
$input->validate();
} catch (RuntimeException $e) {
$output->writeln(
sprintf('<error>Wrong usage: %s</error>', $e->getMessage())
);
exit (EXIT_WRONG_USAGE);
}
$output->setVerbosity(ConsoleOutput::VERBOSITY_NORMAL);
$kernel = new Kernel('dev', true);
$kernel->boot();
if (!$kernel->isDebug() || !(new ConfigCache($kernel->getContainer()->getParameter('debug.container.dump'), true))->isFresh()) {
$buildContainer = \Closure::bind(function () { return $this->buildContainer(); }, $kernel, \get_class($kernel));
$container = $buildContainer();
$container->getCompilerPassConfig()->setRemovingPasses([]);
$container->compile();
} else {
(new XmlFileLoader($container = new ContainerBuilder(), new FileLocator()))->load($kernel->getContainer()->getParameter('debug.container.dump'));
}
$exitStatus = checkServicesInstantiability($container, $output);
exit ($exitStatus);
function getUsedServices($arguments) {
$usedServices = [];
foreach ($arguments as $argument) {
if (is_array($argument)) {
$usedServices = array_merge(getUsedServices($argument), $usedServices);
}
if ($argument instanceof Reference) {
$usedServices[] = $argument->__toString();
}
}
return array_unique($usedServices);
}
function startsWith ($string, $startString): bool {
return (substr($string, 0, strlen($startString)) === $startString);
}
function contains($string, $stringToContains): bool {
return strpos($string, $stringToContains) !== false;
}
function checkServicesInstantiability(ContainerBuilder $container, ConsoleOutput $output): int
{
// TO CHECK
$servicesGetByContainer = [
"logger",
"pim_user.remover.user_group",
"pim_versioning.event_subscriber.purge_progress_bar_advancer",
"pim_versioning.purger.version",
"oro_datagrid.extension.action.type.revoke",
"pim_catalog.query.product_query_builder_factory",
"pim_catalog.repository.locale",
"pim_catalog.saver.locale",
"pim_connector.doctrine.cache_clearer",
"pim_notification.factory.notification",
"pim_notification.notifier",
"pim_user.form.group",
"pim_enrich.extension.action.type.edit_in_modal",
"pim_user.form.handler.group",
"pim_enrich.repository.category",
"pim_enrich.repository.group_type",
"akeneo_elasticsearch.registry.clients",
"pim_versioning.manager.version",
"akeneo.pim.enrichment.controller.product_grid_filter",
"pim_catalog.registry.attribute_type",
"pim_enrich.repository.attribute_group",
"pim_installer.fixture_loader.job_loader",
"pim_enrich.repository.attribute",
"pim_import_export.datagrid.provider.job",
"pim_user.form.handler.acl_role",
"oro_datagrid.extension.action.type.delete",
"akeneo_batch.mail_notifier",
"akeneo_batch.job.job_parameters_validator",
"akeneo_batch.job_parameters_factory",
"pim_enrich.extension.action.type.delete_product",
"pim_enrich.extension.action.type.navigate_product_and_product_model",
"pim_enrich.extension.action.type.toggle_product",
"pim_datagrid.extension.mass_action.type.product_mass_delete",
"pim_datagrid.extension.mass_action.type.sequential_edit",
"pim_datagrid.extension.mass_action.type.export",
"oro_datagrid.extension.action.type.navigate",
"pim_datagrid.extension.mass_action.type.edit",
"akeneo_batch_queue.queue.job_execution_message_repository",
"monolog.logger.batch",
"akeneo.pim.enrichment.controller.product_grid_category_tree",
"akeneo_batch.logger.batch_log_handler",
"akeneo_batch_queue.manager.job_execution_manager",
"akeneo_batch.job.job_registry",
"akeneo_batch.job_repository",
"akeneo_batch_queue.queue.database_job_execution_queue",
"pim_user.context.user",
"pim_catalog.repository.channel",
"akeneo_batch.delete_job_execution",
"oro_datagrid.datagrid.manager",
"akeneo_batch_queue.query.delete_job_execution_message_orphans",
"akeneo_batch.launcher.simple_job_launcher" // USED ONLY BE BEHAT
];
$serviceIds = $container->getServiceIds();
$serviceIds = array_filter($serviceIds, function ($serviceId) { return (startsWith($serviceId, "akeneo") || startsWith($serviceId, "pim")); });
$isUsed = [];
foreach ($serviceIds as $serviceId) {
$isUsed[$serviceId] = false;
}
$isTagged = [];
foreach ($serviceIds as $serviceId) {
$isTagged[$serviceId] = false;
}
foreach ($serviceIds as $serviceId) {
try {
$definition = $container->getDefinition($serviceId);
} catch (\Exception $exception) {
$output->writeln("<error>Service $serviceId not fetchable</error>");
continue;
}
$arguments = $definition->getArguments();
$tags = $definition->getTags();
if ($tags !== []) {
$isTagged[$serviceId] = true;
}
if ($arguments !== []) {
$usedServices = getUsedServices($arguments);
foreach ($usedServices as $usedService) {
$isUsed[$usedService] = true;
}
}
}
$usedServices = array_keys(array_filter($isUsed, function ($isUsed) { return $isUsed; }));
$notUsedServices = array_keys(array_filter($isUsed, function ($isUsed) { return !$isUsed; }));
$taggedServices = array_keys(array_filter($isTagged, function ($isTagged) { return $isTagged; }));
$notTaggedServices = array_keys(array_filter($isTagged, function ($isTagged) { return !$isTagged; }));
$notTaggedServicesAndNotUsed = array_intersect($notUsedServices, $notTaggedServices);
$taggedServicesAndNotUsed = array_intersect($notUsedServices, $taggedServices);
$notUsedServicesAndNotInContainer = array_filter(array_diff($notTaggedServicesAndNotUsed, $servicesGetByContainer), function ($service) { return !contains($service, "controller"); });
$notUsedServicesAndTagged = array_diff($taggedServicesAndNotUsed, $servicesGetByContainer);
sort($notUsedServicesAndNotInContainer);
sort($notUsedServicesAndTagged);
if (count($usedServices) === count($serviceIds)) {
$output->writeln("All services are used!");
return 0;
} else {
$output->writeln("--------------------------------------------------");
$output->writeln("The services found are only starting by 'pim' or 'akeneo' and does not contain 'controller'");
$output->writeln("CAUTION: those services are maybe used inside classes which are ContainerAware");
$output->writeln(
sprintf(
"<comment>Found %s non used services which are not tagged and %s non used services which are tagged (so maybe used through registry).</comment>",
count($notUsedServicesAndNotInContainer),
count($notUsedServicesAndTagged)
)
);
$output->writeln("NOT USED SERVICES AND NOT TAGGED: ");
foreach ($notUsedServicesAndNotInContainer as $serviceId) {
$output->writeln(sprintf('- %s', $serviceId));
}
$output->writeln("NOT USED SERVICES AND TAGGED");
foreach ($notUsedServicesAndTagged as $serviceId) {
$output->writeln(sprintf('- %s', $serviceId));
}
return EXIT_SERVICES_NEVER_USED;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment