Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .claude/agents/code-reviewer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
name: code-reviewer
description: Use this agent when you need comprehensive code review and quality assurance analysis. Examples: After implementing a new feature or function, when refactoring existing code, before merging pull requests, when debugging performance issues, or when ensuring code meets project standards. Example usage: User writes a new authentication function and says 'I just implemented user login functionality, can you review it?' - the assistant should use the code-reviewer agent to analyze the code for security vulnerabilities, best practices, and maintainability.
model: sonnet
color: green
---

You are an expert software engineer specializing in code review and quality assurance. Your primary role is to analyze code for adherence to best practices, maintainability, performance, security, and project-specific standards.

When reviewing code, you will:

**Analysis Framework:**
1. **Functionality**: Verify the code works as intended and handles edge cases appropriately
2. **Security**: Identify potential vulnerabilities, input validation issues, and security anti-patterns
3. **Performance**: Assess algorithmic efficiency, resource usage, and potential bottlenecks
4. **Maintainability**: Evaluate code clarity, documentation, naming conventions, and structural organization
5. **Best Practices**: Check adherence to language-specific conventions and industry standards
6. **Project Standards**: Ensure consistency with existing codebase patterns and established guidelines

**Review Process:**
- Begin with a brief summary of what the code does
- Identify strengths and positive aspects first
- Highlight critical issues (security, bugs) with HIGH priority
- Note performance concerns with MEDIUM priority
- Suggest style and maintainability improvements with LOW priority
- Provide specific, actionable recommendations with code examples when helpful
- Consider the broader context and impact on the overall system

**Output Structure:**
- **Summary**: Brief overview of the code's purpose and overall assessment
- **Critical Issues**: Security vulnerabilities, bugs, or breaking changes
- **Performance Concerns**: Efficiency improvements and optimization opportunities
- **Code Quality**: Maintainability, readability, and best practice adherence
- **Recommendations**: Specific, prioritized suggestions for improvement

Always be constructive and educational in your feedback. When suggesting changes, explain the reasoning behind your recommendations. If the code is well-written, acknowledge this and highlight what makes it effective.
25 changes: 25 additions & 0 deletions .claude/commands/create-new.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
Please create new Contract for $ARGUMENTS.

Follow these steps:

1. Create new Contract Interfaces (`src/Contract/*/`): Public API interfaces for $ARGUMENTS
2. Create new Contract Implementations (`src/Contract/*/`): Wrap static calls for $ARGUMENTS
3. Create new Bundle Interfaces (`src/*/`): Internal interfaces extending contracts for $ARGUMENTS
4. Create new Bundle Implementations (`src/*/`): Final implementations marked `@internal` for $ARGUMENTS

Remember to use the `src/Contract` directory for public API interfaces and the `src` directory for internal bundle implementations.
Remember to create tests for the new contract and bundle implementations.
Remember to use the same naming conventions as existing contracts and bundles.
Remember to use the same namespace structure as in the wrapped class.
- E.g Class to wrap: Pimcore\Model\Document\Hardlink\Service.php
- Contract Interface: `src/Contract/Models/Document/Hardlink/ServiceResolverContractInterface.php`
- Contract Implementation: `src/Contract/Models/Document/Hardlink/ServiceResolverContract.php`
- Bundle Interface: `src/Models/Document/Hardlink/ServiceResolverInterface.php`
- Bundle Implementation: `src/Models/Document/Hardlink/ServiceResolver.php`
- Unit Test: `tests/Unit/Models/Document/Hardlink/ServiceResolverTest.php`
- E.g Class to wrap: Pimcore\Model\Document\Hardlink\Wrapper\Email.php
- Contract Interface: `src/Contract/Models/Document/Hardlink/Wrapper/EmailResolverContractInterface.php`
- Contract Implementation: `src/Contract/Models/Document/Hardlink/Wrapper/EmailResolverContract.php`
- Bundle Interface: `src/Models/Document/Hardlink/Wrapper/EmailResolverInterface.php`
- Bundle Implementation: `src/Models/Document/Hardlink/Wrapper/EmailResolver.php`
- Unit Test: `tests/Unit/Models/Document/Hardlink/Wrapper/EmailResolverTest.php`
19 changes: 19 additions & 0 deletions .claude/commands/docker-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Please run test local in docker container:

Follow these steps:

1. Start docker container if applicable
2. Executel all unit tests
3. Review the test results and ensure all tests pass
4. If any tests fail, investigate the issues and suggest how to fix them

Remember to document any issues or unexpected behavior you encounter during testing.
Remember to use docker commands (`docker`) for any container-related tasks if applicable.
Remember to run test in the docker container.

Testing:

Run all tests**: `vendor/bin/codecept run`



8 changes: 8 additions & 0 deletions .claude/commands/new-line-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Please check local changes for new line:

Follow these steps:

1. Use `git diff` to check the current state of the repository
3. Ignore changes in the `vendor` directory.
2. Check if every php file ends with a new line and ad if not

19 changes: 19 additions & 0 deletions .github/workflows/upstream-merge.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: Upsream Merge

on:
workflow_dispatch:
inputs:
source_branch:
description: 'Source branch to merge from (e.g. 3.1)'
required: true
target_branch:
description: 'Target branch to merge into (e.g. 3.x)'
required: true

jobs:
call-merge:
uses: pimcore/workflows-collection-public/.github/workflows/reusable-upstream-merge.yaml
with:
source_branch: ${{ github.event.inputs.source_branch }}
target_branch: ${{ github.event.inputs.target_branch }}
secrets: inherit
61 changes: 61 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Common Development Commands

### Testing
- Run all tests: `vendor/bin/codecept run`
- Run unit tests only: `vendor/bin/codecept run Unit`
- Run tests with coverage: `vendor/bin/codecept run --coverage`

### Code Quality
- Run PHPStan static analysis: `vendor/bin/phpstan analyse`
- Check PHPStan configuration in `phpstan.neon` (level 6)

### Installation
- Install dependencies: `composer install`
- Install with dev dependencies: `composer install --dev`

## Architecture Overview

This is a Pimcore bundle that wraps static method calls in service-oriented architecture. The bundle follows a consistent 4-layer pattern:

### Core Architecture Pattern
1. **Contract Interfaces** (`src/Contract/*/`): Public API interfaces (e.g., `DbResolverContractInterface`)
2. **Contract Implementations** (`src/Contract/*/`): Wrap static calls (e.g., `DbResolverContract`)
3. **Bundle Interfaces** (`src/*/`): Internal interfaces extending contracts (e.g., `DbResolverInterface`)
4. **Bundle Implementations** (`src/*/`): Final implementations marked `@internal` (e.g., `DbResolver`)

### Key Components
- **Resolver Services**: Transform static calls into injectable services for better testability
- **Proxy Services**: Handle dynamic method interception (deprecated functionality)
- **DI Container**: Auto-configured services via `config/services.yaml`

### Directory Structure
- `src/Contract/`: Public API contracts for third-party developers
- `src/Db/`, `src/Lib/`, `src/Models/`: Bundle-specific implementations (internal use)
- `src/Proxy/`: Legacy proxy functionality (deprecated)
- `tests/Unit/`: Comprehensive unit test coverage

## Development Guidelines

### Adding New Resolvers
1. Create contract interface in `src/Contract/[Category]/`
2. Implement contract wrapping static calls
3. Create bundle-specific interface extending contract
4. Create final implementation marked `@internal`

### Service Registration
Services are auto-registered via PSR-4 in `config/services.yaml`. Manual registration only needed for interface bindings.

### Testing Strategy
- All resolvers have corresponding unit tests in `tests/Unit/`
- Tests use Codeception framework
- Coverage reports enabled in `codeception.dist.yml`

## Important Notes
- Contract interfaces are public API for third-party developers
- Bundle-specific interfaces marked `@internal` are for Pimcore internal use only
- Bundle provides migration path from static methods to dependency injection
- PHPStan baseline exists (`phpstan-baseline.neon`) for existing code
50 changes: 50 additions & 0 deletions src/Contract/Models/Asset/AudioResolverContract.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php
declare(strict_types=1);

/**
* This source file is available under the terms of the
* Pimcore Open Core License (POCL)
* Full copyright and license information is available in
* LICENSE.md which is distributed with this source code.
*
* @copyright Copyright (c) Pimcore GmbH (https://www.pimcore.com)
* @license Pimcore Open Core License (POCL)
*/

namespace Pimcore\Bundle\StaticResolverBundle\Contract\Models\Asset;

use Exception;
use Pimcore\Model\Asset;
use Pimcore\Model\Asset\Audio;
use Pimcore\Model\Asset\Listing;

class AudioResolverContract implements AudioResolverContractInterface
{
/**
* @throws Exception
*/
public function getList(array $config = []): Listing
{
return Audio::getList($config);
}

public function getByPath(string $path, array $params = []): ?Audio
{
return Audio::getByPath($path, $params);
}

public function getTypes(): array
{
return Audio::getTypes();
}

public function create(int $parentId, array $data = [], bool $save = true): Asset
{
return Audio::create($parentId, $data, $save);
}

public function getById(int $id, array $params = []): ?Audio
{
return Audio::getById($id, $params);
}
}
35 changes: 35 additions & 0 deletions src/Contract/Models/Asset/AudioResolverContractInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php
declare(strict_types=1);

/**
* This source file is available under the terms of the
* Pimcore Open Core License (POCL)
* Full copyright and license information is available in
* LICENSE.md which is distributed with this source code.
*
* @copyright Copyright (c) Pimcore GmbH (https://www.pimcore.com)
* @license Pimcore Open Core License (POCL)
*/

namespace Pimcore\Bundle\StaticResolverBundle\Contract\Models\Asset;

use Exception;
use Pimcore\Model\Asset;
use Pimcore\Model\Asset\Audio;
use Pimcore\Model\Asset\Listing;

interface AudioResolverContractInterface
{
/**
* @throws Exception
*/
public function getList(array $config = []): Listing;

public function getByPath(string $path, array $params = []): ?Audio;

public function getTypes(): array;

public function create(int $parentId, array $data = [], bool $save = true): Asset;

public function getById(int $id, array $params = []): ?Audio;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php
declare(strict_types=1);

/**
* This source file is available under the terms of the
* Pimcore Open Core License (POCL)
* Full copyright and license information is available in
* LICENSE.md which is distributed with this source code.
*
* @copyright Copyright (c) Pimcore GmbH (https://www.pimcore.com)
* @license Pimcore Open Core License (POCL)
*/

namespace Pimcore\Bundle\StaticResolverBundle\Contract\Models\DataObject\Classificationstore;

use Pimcore\Model\DataObject\Classificationstore\KeyGroupRelation;

class KeyGroupRelationResolverContract implements KeyGroupRelationResolverContractInterface
{
public function create(): KeyGroupRelation
{
return KeyGroupRelation::create();
}

public function getByGroupAndKeyId(int $groupId, int $keyId): ?KeyGroupRelation
{
return KeyGroupRelation::getByGroupAndKeyId($groupId, $keyId);
}

public function locateDaoClass(string $modelClass): ?string
{
return KeyGroupRelation::locateDaoClass($modelClass);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php
declare(strict_types=1);

/**
* This source file is available under the terms of the
* Pimcore Open Core License (POCL)
* Full copyright and license information is available in
* LICENSE.md which is distributed with this source code.
*
* @copyright Copyright (c) Pimcore GmbH (https://www.pimcore.com)
* @license Pimcore Open Core License (POCL)
*/

namespace Pimcore\Bundle\StaticResolverBundle\Contract\Models\DataObject\Classificationstore;

use Pimcore\Model\DataObject\Classificationstore\KeyGroupRelation;

interface KeyGroupRelationResolverContractInterface
{
public function create(): KeyGroupRelation;

public function getByGroupAndKeyId(int $groupId, int $keyId): ?KeyGroupRelation;

public function locateDaoClass(string $modelClass): ?string;
}
Loading
Loading