Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
75.47% covered (warning)
75.47%
40 / 53
40.00% covered (danger)
40.00%
2 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
ContentHelper
75.47% covered (warning)
75.47%
40 / 53
40.00% covered (danger)
40.00%
2 / 5
14.13
0.00% covered (danger)
0.00%
0 / 1
 enhanceContent
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 enhanceContentAlignment
100.00% covered (success)
100.00%
29 / 29
100.00% covered (success)
100.00%
1 / 1
5
 processResponsiveImages
63.64% covered (warning)
63.64%
7 / 11
0.00% covered (danger)
0.00%
0 / 1
2.19
 processMarkdown
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 processMarkdownAlignmentSyntax
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2declare(strict_types=1);
3
4namespace App\View\Helper;
5
6use Cake\View\Helper;
7
8/**
9 * Content Helper
10 *
11 * Handles content enhancement and formatting:
12 * - Content alignment helpers
13 * - Responsive image processing
14 * - Markdown processing with custom syntax
15 *
16 * Note: Video and gallery placeholder processing is handled by VideoHelper and GalleryHelper
17 */
18class ContentHelper extends Helper
19{
20    /**
21     * List of helpers used by this helper
22     *
23     * @var array<string>
24     */
25    protected array $helpers = ['Html'];
26
27    /**
28     * Enhance content formatting without processing placeholders
29     * Note: Video and gallery placeholders should be processed by their respective helpers first
30     *
31     * @param string $content Raw content (placeholders should already be processed)
32     * @param array $options Processing options
33     * @return string Enhanced content
34     */
35    public function enhanceContent(string $content, array $options = []): string
36    {
37        // Content enhancement pipeline (no placeholder processing)
38        $content = $this->enhanceContentAlignment($content, $options);
39
40        // Only process responsive images if explicitly requested
41        if ($options['processResponsiveImages'] ?? false) {
42            $content = $this->processResponsiveImages($content, $options);
43        }
44
45        return $content;
46    }
47
48    /**
49     * Enhance content alignment by adding CSS classes and data attributes
50     *
51     * @param string $content HTML content
52     * @param array $options Processing options
53     * @return string Enhanced content
54     */
55    public function enhanceContentAlignment(string $content, array $options = []): string
56    {
57        // Add alignment helper classes to paragraphs with inline styles
58        $alignmentResult = preg_replace(
59            '/<p([^>]*style[^>]*text-align:\s*(center|left|right|justify)[^>]*)>/i',
60            '<p$1 class="content-align-$2">',
61            $content,
62        );
63        if ($alignmentResult !== null) {
64            $content = $alignmentResult;
65        }
66
67        // Add content-image class to all images for consistent styling
68        $imageClassResult = preg_replace(
69            '/<img([^>]*)>/i',
70            '<img$1 class="content-image">',
71            $content,
72        );
73        if ($imageClassResult !== null) {
74            $content = $imageClassResult;
75        }
76
77        // Preserve line breaks within aligned content by converting double BR to paragraph breaks
78        $lineBreakResult = preg_replace(
79            '/<br\s*\/?>\s*<br\s*\/?>/i',
80            '</p><p>',
81            $content,
82        );
83        if ($lineBreakResult !== null) {
84            $content = $lineBreakResult;
85        }
86
87        // Ensure empty paragraphs with alignment are preserved for spacing
88        $emptyParagraphResult = preg_replace(
89            '/<p([^>]*style[^>]*text-align[^>]*)>\s*<\/p>/i',
90            '<p$1>&nbsp;</p>',
91            $content,
92        );
93        if ($emptyParagraphResult !== null) {
94            $content = $emptyParagraphResult;
95        }
96
97        return $content;
98    }
99
100    /**
101     * Process images to make them responsive and add proper styling
102     *
103     * @param string $content HTML content with images
104     * @param array $options Processing options
105     * @return string Content with responsive images
106     */
107    public function processResponsiveImages(string $content, array $options = []): string
108    {
109        // Only add loading="lazy" and avoid adding classes that might break existing functionality
110        $content = preg_replace_callback(
111            '/<img([^>]*)>/i',
112            function ($matches) {
113                $attributes = $matches[1];
114
115                // Add loading="lazy" if not present
116                if (!preg_match('/loading\s*=/i', $attributes)) {
117                    $attributes .= ' loading="lazy"';
118                }
119
120                // Don't add img-responsive class automatically - it was breaking galleries
121
122                return '<img' . $attributes . '>';
123            },
124            $content,
125        );
126
127        return $content;
128    }
129
130    /**
131     * Process Markdown content with enhanced alignment support
132     * Note: Video and gallery placeholders should be processed by helpers after markdown conversion
133     *
134     * @param string $markdown Markdown content
135     * @param array $options Processing options
136     * @return string Processed markdown with custom syntax converted
137     */
138    public function processMarkdown(string $markdown, array $options = []): string
139    {
140        // Enhanced Markdown processing with alignment helpers
141        return $this->processMarkdownAlignmentSyntax($markdown, $options);
142    }
143
144    /**
145     * Process custom Markdown alignment syntax
146     *
147     * @param string $markdown Markdown content
148     * @param array $options Processing options
149     * @return string Enhanced Markdown
150     */
151    private function processMarkdownAlignmentSyntax(string $markdown, array $options = []): string
152    {
153        // Convert alignment markers to HTML
154        $alignmentPatterns = [
155            '/^->(.+)<-$/m' => '<p style="text-align: center;">$1</p>',
156            '/^->(.+)$/m' => '<p style="text-align: right;">$1</p>',
157            '/^<-(.+)->$/m' => '<p style="text-align: justify;">$1</p>',
158        ];
159
160        foreach ($alignmentPatterns as $pattern => $replacement) {
161            $markdown = preg_replace($pattern, $replacement, $markdown);
162        }
163
164        return $markdown;
165    }
166}