PHP code example of c975l / ui-bundle

1. Go to this page and download the library: Download c975l/ui-bundle library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

c975l / ui-bundle example snippets


->add('plainPassword', PasswordType::class, [
    'attr' => ['data-password-pattern' => ''],
])
->add('confirmPassword', PasswordType::class, [
    'attr' => ['data-password-confirm' => 'registration_form_plainPassword'],
])

use c975L\UiBundle\Contract\HasBlocksInterface;
use c975L\UiBundle\Entity\Block;
use c975L\UiBundle\Entity\Trait\HasBlocksTrait;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;

class Page implements HasBlocksInterface
{
    use HasBlocksTrait;

    #[ORM\ManyToMany(targetEntity: Block::class, cascade: ['persist', 'remove'])]
    #[ORM\JoinTable(name: 'site_page_block')]
    #[ORM\OrderBy(['position' => 'ASC'])]
    private Collection $blocks;

    public function __construct()
    {
        $this->blocks = new ArrayCollection();
    }
}

use c975L\UiBundle\Form\BlockType;

class PageCrudController extends AbstractCrudController
{
    public function configureFields(string $pageName): iterable
    {
        return [
            // ...
            CollectionField::new('blocks')
                ->setLabel(t('label.blocks', [], 'ui'))
                ->setEntryType(BlockType::class)
                ->allowAdd()
                ->allowDelete()
                ->setFormTypeOption('by_reference', false)
                ->hideOnIndex(),
        ];
    }
}

use c975L\UiBundle\Form\Block\HasAnchorFieldTrait;
use c975L\UiBundle\Service\BlockAnchorSlugger;

class MySectionType extends AbstractType
{
    use HasAnchorFieldTrait;

    public function __construct(private readonly BlockAnchorSlugger $anchorSlugger)
    {
    }

    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $this->addAnchorField($builder, $this->anchorSlugger); // 2nd arg: title field name, defaults to "title"
        // ...your own fields...
    }
}

use c975L\UiBundle\Form\Block\HasBackgroundFieldTrait;

class MySectionType extends AbstractType
{
    use HasBackgroundFieldTrait;

    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $this->addBackgroundField($builder);
        // ...your own fields...
    }
}

CollectionField::new('blocks')
    ->setEntryType(BlockType::class)
    ->setFormTypeOptions(['context' => 'menu'])
    // ...

use c975L\UiBundle\Contract\PlaceholderMediaProviderInterface;

class ShowcasePlaceholderMediaProvider implements PlaceholderMediaProviderInterface
{
    public function getPlaceholderMedia(): array
    {
        return [
            'images' => ['medias/showcase/photo-1.webp', 'medias/showcase/photo-2.webp'],
            'video' => 'medias/showcase/clip.mp4',
            'video_embed' => 'medias/showcase/clip-embed.html',
            'audio' => 'medias/showcase/loop.mp3',
            'document' => 'medias/showcase/brochure.pdf',
        ];
    }
}

use c975L\UiBundle\Contract\BlockFixtureProviderInterface;

class BookingBlockFixtureProvider implements BlockFixtureProviderInterface
{
    public function getFixtures(): array
    {
        return [
            'booking' => [
                '' => ['title' => 'Réserver une table'],
            ],
        ];
    }
}

use c975L\UiBundle\Contract\GalleryShowcaseProviderInterface;
use Twig\Environment;

class BookingGalleryShowcaseProvider implements GalleryShowcaseProviderInterface
{
    public function __construct(private Environment $twig) {}

    public function getShowcases(): array
    {
        return [
            'Booking widget' => [
                'description' => 'Available layouts for the standalone booking widget.',
                // "kind" ties this to "booking"'s own category and suppresses its own regular preview
                // card (which would otherwise show up empty right next to this one) - use null if there's
                // no real block kind at all (e.g. share_buttons()). "category" overrides the category
                // directly instead (no suppression) - for a kind-less showcase that still belongs next
                // to a related one, e.g. reusing a sibling kind's own category key.
                'kind' => 'booking',
                'variants' => [
                    'Compact' => $this->twig->render('@App/booking/widget.html.twig', ['layout' => 'compact']),
                    'Full' => $this->twig->render('@App/booking/widget.html.twig', ['layout' => 'full']),
                ],
            ],
        ];
    }
}

use c975L\UiBundle\Form\CaptchaType;

$builder->add('captcha', CaptchaType::class, [
    // Reported to Google alongside the token, so the admin console can break scores down per form
    'action_name' => 'contact',
]);

TextareaField::new('summary')
    ->setFormTypeOption('attr', ['data-ai-rephrase' => 'true']),

use c975L\UiBundle\Contract\BlockCacheTagProviderInterface;
use c975L\UiBundle\Entity\Block;

class ArticlesSliderCacheTagProvider implements BlockCacheTagProviderInterface
{
    public function getCacheTagResolvers(): array
    {
        return [
            'articles_slider' => fn (Block $block): array => ['articles_slider_' . $block->getData()['pageId']],
        ];
    }
}

use c975L\UiBundle\Contract\CollectionSourceProviderInterface;
use c975L\UiBundle\Model\CollectionItem;

class BookCollectionSourceProvider implements CollectionSourceProviderInterface
{
    public function __construct(private BookRepository $books) {}

    public function getSources(): array
    {
        return [
            'book.collection.books' => [
                'label' => 'Books',
                'items' => function (?int $limit): iterable {
                    foreach ($this->books->findLatest($limit) as $book) {
                        yield new CollectionItem(
                            title: $book->getTitle(),
                            description: $book->getSummary(),
                            imageUrl: $book->getCoverUrl(),
                            url: $book->getUrl(),
                        );
                    }
                },
            ],
        ];
    }
}

'items' => function (?int $limit): iterable { /* ... */ },
'detail' => fn (string $slug): ?array => $this->books->findOneBySlug($slug)?->toDetailData(),

yield new CollectionItem(
    title: $book->getTitle(),
    // ...
    slug: $book->getSlug(),
);

use c975L\UiBundle\Entity\Media;

Media::ROLE_FAVICON;          // 'favicon'
Media::ROLE_APPLE_TOUCH_ICON; // 'apple-touch-icon'
Media::ROLE_OG_IMAGE;         // 'og-image'
Media::ROLE_LOGO;             // 'logo'

use c975L\UiBundle\Contract\MediaUsageProviderInterface;
use c975L\UiBundle\Entity\Media;

class MyMediaUsageProvider implements MediaUsageProviderInterface
{
    public function getUsages(array $medias): array
    {
        // [mediaId => [['label' => string, 'url' => ?string], ...], ...]
        return [...];
    }
}

use c975L\UiBundle\Contract\BundleStylesheetProviderInterface;

class StylesheetProvider implements BundleStylesheetProviderInterface
{
    public function getStylesheets(): array
    {
        return [
            'bundles/mybundle/css/styles.min.css', // local public asset
            'assets/styles/themes/mybundle.css', // the app's own sheet, served by AssetMapper
            'https://cdn.example.com/lib/styles.min.css', // CDN URL, passed through as-is
        ];
    }
}

namespace App\Service;

use c975L\UiBundle\Contract\BundleStylesheetProviderInterface;

class ThemeStylesheetProvider implements BundleStylesheetProviderInterface
{
    public function getStylesheets(): array
    {
        return [
            'assets/styles/themes/ui.css',
            'assets/styles/themes/site.css',
        ];
    }
}

use c975L\UiBundle\Contract\BundleStylesheetManagementProviderInterface;

class StylesheetProvider implements BundleStylesheetManagementProviderInterface
{
    public function getManagementStylesheets(): array
    {
        return [
            'bundles/mybundle/css/management.min.css',
        ];
    }
}

use c975L\UiBundle\Registry\StylesheetManagementRegistry;

public function __construct(
    private readonly StylesheetManagementRegistry $stylesheetManagementRegistry,
) {}

public function configureAssets(): Assets
{
    $assets = Assets::new();

    foreach ($this->stylesheetManagementRegistry->all() as $stylesheet) {
        $assets->addCssFile($stylesheet);
    }

    return $assets;
}

use c975L\UiBundle\Testing\ComponentCenteringAnalyzer;
use c975L\UiBundle\Testing\StylesheetCascade;

$analyzer = new ComponentCenteringAnalyzer(StylesheetCascade::fromFiles(
    $uiBundleDir . '/public/css/styles.css',   // load order matters: source order decides between two rules of equal specificity
    $myBundleDir . '/public/css/styles.css',
));

foreach ($analyzer->analyse(ComponentCenteringAnalyzer::tagsByClass($myBundleDir . '/templates/components'))['violations'] as $violation) {
    self::fail(ComponentCenteringAnalyzer::describe($violation));
}
bash
php bin/console doctrine:migrations:diff
php bin/console doctrine:migrations:migrate
bash
php bin/console doctrine:migrations:diff
php bin/console doctrine:migrations:migrate
twig
{{ legal_model_html('france/terms-of-sales', '2026-01-01') }}
bash
php bin/console c975l:ui:media-dimensions