From ed4ac7a07326bf7a376e6d56e643b9df797df40e Mon Sep 17 00:00:00 2001 From: Emily Date: Thu, 23 Jul 2026 22:10:31 -0700 Subject: [PATCH 1/3] Add Symfony lock test Signed-off-by: Emily --- tests/packagedcode/data/phpcomposer/symfony.lock | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 tests/packagedcode/data/phpcomposer/symfony.lock diff --git a/tests/packagedcode/data/phpcomposer/symfony.lock b/tests/packagedcode/data/phpcomposer/symfony.lock new file mode 100644 index 0000000000..ca0690e6cd --- /dev/null +++ b/tests/packagedcode/data/phpcomposer/symfony.lock @@ -0,0 +1,8 @@ +{ + "symfony/console": { + "version": "5.4" + }, + "symfony/flex": { + "version": "1.20" + } +} From 32b0d4e1c0dfdd6ee9e7b63dfa058b99c5a5c366 Mon Sep 17 00:00:00 2001 From: Emily Date: Sun, 9 Aug 2026 21:34:59 -0700 Subject: [PATCH 2/3] Add Symfony lockfile package parsing Signed-off-by: Emily --- src/packagedcode/__init__.py | 1 + src/packagedcode/phpcomposer.py | 55 +++++++++++++++++++ .../data/phpcomposer/symfony.lock | 5 +- tests/packagedcode/test_phpcomposer.py | 24 ++++++++ 4 files changed, 84 insertions(+), 1 deletion(-) diff --git a/src/packagedcode/__init__.py b/src/packagedcode/__init__.py index fc1e490eef..5e59c6a8bb 100644 --- a/src/packagedcode/__init__.py +++ b/src/packagedcode/__init__.py @@ -161,6 +161,7 @@ phpcomposer.PhpComposerJsonHandler, phpcomposer.PhpComposerLockHandler, + phpcomposer.PhpSymfonyLockHandler, pubspec.DartPubspecYamlHandler, pubspec.DartPubspecLockHandler, diff --git a/src/packagedcode/phpcomposer.py b/src/packagedcode/phpcomposer.py index 5a3ee59af1..199601cbb1 100644 --- a/src/packagedcode/phpcomposer.py +++ b/src/packagedcode/phpcomposer.py @@ -207,6 +207,61 @@ def parse(cls, location, package_only=False): for package in packages + packages_dev: yield package +class PhpSymfonyLockHandler(models.DatafileHandler): + datasource_id = 'php_symfony_lock' + path_patterns = ('*symfony.lock',) + default_package_type = 'composer' + default_primary_language = 'PHP' + is_lockfile = True + description = 'Symfony Flex lockfile' + documentation_url = 'https://symfony.com/doc/current/setup/flex.html' + + @classmethod + def parse(cls, location, package_only=False): + with io.open(location, encoding='utf-8') as loc: + lock_data = json.load(loc) + + if not isinstance(lock_data, dict): + return + + dependencies = [] + + for package_name, package_details in lock_data.items(): + if not isinstance(package_details, dict): + continue + + namespace, separator, name = package_name.rpartition('/') + + if not separator or not namespace or not name: + continue + + version = package_details.get('version') + if not isinstance(version, str): + version = None + else: + version = version.strip() + + if not version: + version = None + + purl = models.PackageURL( + type=cls.default_package_type, + namespace=namespace, + name=name, + version=version, + ).to_string() + + dependency = models.DependentPackage( + purl=purl, + extracted_requirement=version, + is_pinned=bool(version), + ) + + dependencies.append(dependency) + + yield cls.create_default_package_data( + dependencies=dependencies, + ) def licensing_mapper(licenses, package, is_private=False): """ diff --git a/tests/packagedcode/data/phpcomposer/symfony.lock b/tests/packagedcode/data/phpcomposer/symfony.lock index ca0690e6cd..c06bed3416 100644 --- a/tests/packagedcode/data/phpcomposer/symfony.lock +++ b/tests/packagedcode/data/phpcomposer/symfony.lock @@ -1,8 +1,11 @@ { + "composer/pcre": { + "version": "1.0.0" + }, "symfony/console": { "version": "5.4" }, "symfony/flex": { "version": "1.20" } -} +} diff --git a/tests/packagedcode/test_phpcomposer.py b/tests/packagedcode/test_phpcomposer.py index 4de0e451ec..e2e965cd69 100644 --- a/tests/packagedcode/test_phpcomposer.py +++ b/tests/packagedcode/test_phpcomposer.py @@ -86,3 +86,27 @@ def test_parse_composer_lock(self): expected_loc = self.get_test_loc('phpcomposer/composer.lock-expected.json') packages = phpcomposer.PhpComposerLockHandler.parse(test_file) self.check_packages_data(packages, expected_loc, regen=REGEN_TEST_FIXTURES) + + def test_is_manifest_php_symfony_lock(self): + test_file = self.get_test_loc('phpcomposer/symfony.lock') + assert phpcomposer.PhpSymfonyLockHandler.is_datafile(test_file) + + def test_parse_symfony_lock(self): + test_file = self.get_test_loc('phpcomposer/symfony.lock') + + package_data = list( + phpcomposer.PhpSymfonyLockHandler.parse(test_file) + ) + + assert len(package_data) == 1 + + dependencies = package_data[0].dependencies + actual_purls = {dependency.purl for dependency in dependencies} + + expected_purls = { + 'pkg:composer/composer/pcre@1.0.0', + 'pkg:composer/symfony/console@5.4', + 'pkg:composer/symfony/flex@1.20', + } + + assert actual_purls == expected_purls From e8881f0cd16e4fe2061f3b9a98689c4590f946d3 Mon Sep 17 00:00:00 2001 From: Emily Date: Mon, 10 Aug 2026 01:47:10 -0700 Subject: [PATCH 3/3] Update package list fixture for Symfony lock Signed-off-by: Emily --- tests/packagedcode/data/plugin/plugins_list_linux.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/packagedcode/data/plugin/plugins_list_linux.txt b/tests/packagedcode/data/plugin/plugins_list_linux.txt index 34078bc580..d1972b580e 100755 --- a/tests/packagedcode/data/plugin/plugins_list_linux.txt +++ b/tests/packagedcode/data/plugin/plugins_list_linux.txt @@ -181,6 +181,13 @@ Package type: composer description: PHP composer lockfile path_patterns: '*composer.lock' -------------------------------------------- +Package type: composer + datasource_id: php_symfony_lock + documentation URL: https://symfony.com/doc/current/setup/flex.html + primary language: PHP + description: Symfony Flex lockfile + path_patterns: '*symfony.lock' +-------------------------------------------- Package type: conan datasource_id: conan_conandata_yml documentation URL: https://docs.conan.io/2/tutorial/creating_packages/handle_sources_in_packages.html#using-the-conandata-yml-file