PluginProbe ʕ •ᴥ•ʔ
AlphaListing / 4.3.7
AlphaListing v4.3.7
trunk 4.3.4 4.3.5 4.3.6 4.3.7 4.4.0
alphalisting / src / Shortcode / QueryParts / ColumnWidth.php
alphalisting / src / Shortcode / QueryParts Last commit date
Alphabet.php 6 months ago ColumnGap.php 6 months ago ColumnWidth.php 6 months ago Columns.php 6 months ago ExcludePosts.php 6 months ago ExcludeTerms.php 6 months ago HideEmptyTerms.php 6 months ago HideEmpty_Deprecated.php 6 months ago InstanceId.php 6 months ago ParentPost.php 6 months ago ParentTermCommon.php 6 months ago ParentTermId.php 6 months ago ParentTermSlugOrId.php 6 months ago PostType.php 6 months ago PostsTerms.php 6 months ago SymbolsFirst.php 6 months ago Taxonomy.php 6 months ago TermsCommon.php 6 months ago TermsTerms.php 6 months ago
ColumnWidth.php
145 lines
1 <?php
2 /**
3 * Alphabet Query Part.
4 *
5 * @package alphalisting
6 */
7
8 declare(strict_types=1);
9
10 namespace eslin87\AlphaListing\Shortcode\QueryParts;
11
12 if (!defined("ABSPATH")) {
13 exit();
14 }
15
16 use eslin87\AlphaListing\Shortcode\Extension;
17
18 /**
19 * Column Width Query Part extension
20 */
21 class ColumnWidth extends Extension {
22 private const ALLOWED_UNITS = ['px', 'em', 'rem', '%', 'ch'];
23 private const MAX_PIXEL_VALUE = 1200.0;
24 private const MAX_PERCENT_VALUE = 100.0;
25 public const DEFAULT_COLUMN_WIDTH = '15em';
26
27 /**
28 * The attribute for this Query Part.
29 *
30 * @since 4.0.0
31 * @var string
32 */
33 public $attribute_name = 'column-width';
34
35 /**
36 * The column width.
37 *
38 * @var string
39 */
40 public $column_width = self::DEFAULT_COLUMN_WIDTH;
41
42 /**
43 * Sanitize the shortcode attribute.
44 *
45 * @param mixed $value The value of the shortcode attribute.
46 * @param array $attributes The complete set of shortcode attributes.
47 * @return string
48 */
49 public function sanitize_attribute($value, array $attributes) {
50 return $this->sanitize_css_length($value, self::DEFAULT_COLUMN_WIDTH);
51 }
52
53 /**
54 * Update the query with this extension's additional configuration.
55 *
56 * @param \AlphaListing\Query $query The query.
57 * @param string $display The display/query type.
58 * @param string $key The name of the attribute.
59 * @param mixed $value The shortcode attribute value.
60 * @param array $attributes The complete set of shortcode attributes.
61 * @return mixed The updated query.
62 */
63 public function shortcode_query($query, string $display, string $key, $value, array $attributes) {
64 $this->column_width = $this->sanitize_css_length($value, self::DEFAULT_COLUMN_WIDTH);
65 $this->add_hook('filter', 'alphalisting_styles', [$this, 'return_styles'], 10, 3);
66 return $query;
67 }
68
69 /**
70 * Return the stylesheet for this instance.
71 *
72 * @param string $styles The stylesheet.
73 * @return string
74 */
75 public function return_styles($styles): string {
76 return sprintf('%s --alphalisting-column-width: %s; ', $styles, $this->column_width);
77 }
78
79 /**
80 * Ensure the provided column width is a safe CSS length value.
81 *
82 * @param mixed $value Potential CSS length value.
83 * @param string $default Default value to use when sanitization fails.
84 * @return string
85 */
86 private function sanitize_css_length($value, string $default): string {
87 if (is_string($value)) {
88 $value = trim($value);
89 } elseif (is_numeric($value)) {
90 $value = (string) $value;
91 } else {
92 return $default;
93 }
94
95 if ('' === $value) {
96 return $default;
97 }
98
99 if (preg_match('/^0+(?:\.0+)?$/', $value)) {
100 return '0';
101 }
102
103 if (!preg_match('/^([0-9]+(?:\.[0-9]+)?)\s*(px|em|rem|%|ch)$/i', $value, $matches)) {
104 return $default;
105 }
106
107 $number = (float) $matches[1];
108 $unit = strtolower($matches[2]);
109
110 if (!in_array($unit, self::ALLOWED_UNITS, true)) {
111 return $default;
112 }
113
114 if ($number < 0) {
115 return $default;
116 }
117
118 if ('px' === $unit) {
119 $number = min($number, self::MAX_PIXEL_VALUE);
120 }
121
122 if (in_array($unit, ['%', 'ch'], true)) {
123 $number = min($number, self::MAX_PERCENT_VALUE);
124 }
125
126 $number_string = $this->format_numeric_value($number);
127
128 return $number_string . $unit;
129 }
130
131 /**
132 * Normalize numeric values before concatenating with units.
133 *
134 * @param float $number The numeric value to format.
135 * @return string
136 */
137 private function format_numeric_value(float $number): string {
138 if (floor($number) === $number) {
139 return (string) (int) $number;
140 }
141
142 return rtrim(rtrim(sprintf('%.4f', $number), '0'), '.');
143 }
144 }
145