diff --git a/.github/.readthedocs.yaml b/.github/.readthedocs.yaml new file mode 100644 index 0000000000..9753f83314 --- /dev/null +++ b/.github/.readthedocs.yaml @@ -0,0 +1,25 @@ +# Read the Docs configuration file for Sphinx projects +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +build: + os: ubuntu-24.04 + tools: + python: "3.12" + jobs: + post_create_environment: + - python -m pip install sphinx-rtd-theme + +# Build documentation in the "doc/" directory with Sphinx +sphinx: + configuration: doc/conf.py + # Fail on all warnings to avoid broken references + # fail_on_warning: true + +# Optionally build your docs in additional formats such as PDF and ePub +formats: + - pdf + - epub + - htmlzip diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 8dcb4ec5f9..7cfde02b77 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -63,15 +63,15 @@ jobs: test-php: name: Test on PHP ${{ matrix.php-version }}, ${{ matrix.composer-dependency }} and ${{ matrix.os }} runs-on: ${{ matrix.os }} - continue-on-error: ${{ matrix.php-version == '8.4' }} + continue-on-error: ${{ matrix.php-version == '8.5' }} strategy: matrix: - php-version: ['8.2', '8.3'] + php-version: ['8.2', '8.3', '8.4'] os: [ubuntu-latest] composer-dependency: [locked, highest] php-extensions: ['mbstring, iconv, mysqli, zip, gd, bz2'] include: - - php-version: '8.4' + - php-version: '8.5' os: ubuntu-latest composer-dependency: locked composer-options: '--ignore-platform-req=php+' diff --git a/docs/conf.py b/docs/conf.py index d79a969eac..c09030aba8 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -44,7 +44,7 @@ master_doc = 'index' # General information about the project. project = u'phpMyAdmin' -copyright = u'2012 - 2023, The phpMyAdmin devel team' +copyright = u'2012 - 2024, The phpMyAdmin devel team' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -100,6 +100,16 @@ pygments_style = 'sphinx' # a list of builtin themes. html_theme = 'default' +# See: https://docs.readthedocs.io/en/stable/reference/environment-variables.html#envvar-READTHEDOCS +on_rtd = os.environ.get('READTHEDOCS', None) == 'True' + +if on_rtd: # only import and set the theme if we're building docs on readthedocs + try: + import sphinx_rtd_theme + html_theme = 'sphinx_rtd_theme' + except: + html_theme = 'default' + # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 7ffdca2d1f..5a0fd25b84 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -8529,7 +8529,7 @@ parameters: - message: '#^Argument of an invalid type mixed supplied for foreach, only iterables are supported\.$#' identifier: foreach.nonIterable - count: 2 + count: 1 path: src/Error/ErrorReport.php - diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 11c9a484e7..6c0eeffd62 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -5281,6 +5281,7 @@ + diff --git a/resources/js/src/sql.ts b/resources/js/src/sql.ts index eda96b949b..21b619cf14 100644 --- a/resources/js/src/sql.ts +++ b/resources/js/src/sql.ts @@ -5,7 +5,7 @@ import { Navigation } from './modules/navigation.ts'; import { CommonParams } from './modules/common.ts'; import highlightSql from './modules/sql-highlight.ts'; import { ajaxRemoveMessage, ajaxShowMessage } from './modules/ajax-message.ts'; -import { escapeHtml } from './modules/functions/escape.ts'; +import { escapeBacktick, escapeHtml } from './modules/functions/escape.ts'; import refreshMainContent from './modules/functions/refreshMainContent.ts'; import isStorageSupported from './modules/functions/isStorageSupported.ts'; @@ -320,7 +320,7 @@ const insertQuery = function (queryType) { // @ts-ignore var myListBox = document.sqlform.dummy; // @ts-ignore - table = document.sqlform.table.value; + table = escapeBacktick(document.sqlform.table.value); if (myListBox.options.length > 0) { sqlBoxLocked = true; diff --git a/resources/js/src/table/gis_visualization.ts b/resources/js/src/table/gis_visualization.ts index 3530245920..7a1cc869a1 100644 --- a/resources/js/src/table/gis_visualization.ts +++ b/resources/js/src/table/gis_visualization.ts @@ -387,7 +387,7 @@ class SvgVisualization extends GisVisualization { $('#tooltip').remove(); const target = event.target as SVGElement; - const contents = target.getAttribute('name').trim(); + const contents = target.getAttribute('data-label').trim(); if (contents === '') { return; } diff --git a/resources/templates/table/insert/column_row.twig b/resources/templates/table/insert/column_row.twig index 5f1d86ce67..2b1e960924 100644 --- a/resources/templates/table/insert/column_row.twig +++ b/resources/templates/table/insert/column_row.twig @@ -55,7 +55,7 @@ {% elseif (longtext_double_textarea and 'longtext' in column.pmaType) or 'json' in column.pmaType or 'text' in column.pmaType %} {{ backup_field|raw }} @@ -98,7 +98,7 @@ {{ backup_field|raw }} diff --git a/src/Error/ErrorReport.php b/src/Error/ErrorReport.php index 7a7444bbaf..05ebb88cee 100644 --- a/src/Error/ErrorReport.php +++ b/src/Error/ErrorReport.php @@ -226,12 +226,14 @@ class ErrorReport private function translateStacktrace(array $stack): array { foreach ($stack as &$level) { - foreach ($level['context'] as &$line) { - if (mb_strlen($line) <= 80) { - continue; - } + if (is_array($level['context'])) { + foreach ($level['context'] as &$line) { + if (mb_strlen($line) <= 80) { + continue; + } - $line = mb_substr($line, 0, 75) . '//...'; + $line = mb_substr($line, 0, 75) . '//...'; + } } [$uri, $scriptName] = $this->sanitizeUrl($level['url']); diff --git a/src/Gis/GisLineString.php b/src/Gis/GisLineString.php index bb58d85ee4..4816a85099 100644 --- a/src/Gis/GisLineString.php +++ b/src/Gis/GisLineString.php @@ -167,7 +167,7 @@ class GisLineString extends GisGeometry public function prepareRowAsSvg(string $spatial, string $label, array $color, ScaleData $scaleData): string { $lineOptions = [ - 'name' => $label, + 'data-label' => $label, 'id' => $label . $this->getRandomId(), 'class' => 'linestring vector', 'fill' => 'none', diff --git a/src/Gis/GisMultiLineString.php b/src/Gis/GisMultiLineString.php index 214215ba6f..50dfc53782 100644 --- a/src/Gis/GisMultiLineString.php +++ b/src/Gis/GisMultiLineString.php @@ -188,7 +188,7 @@ class GisMultiLineString extends GisGeometry public function prepareRowAsSvg(string $spatial, string $label, array $color, ScaleData $scaleData): string { $lineOptions = [ - 'name' => $label, + 'data-label' => $label, 'class' => 'linestring vector', 'fill' => 'none', 'stroke' => sprintf('#%02x%02x%02x', ...$color), diff --git a/src/Gis/GisMultiPoint.php b/src/Gis/GisMultiPoint.php index 2aa374eff8..2fb02121c1 100644 --- a/src/Gis/GisMultiPoint.php +++ b/src/Gis/GisMultiPoint.php @@ -169,7 +169,7 @@ class GisMultiPoint extends GisGeometry public function prepareRowAsSvg(string $spatial, string $label, array $color, ScaleData $scaleData): string { $pointOptions = [ - 'name' => $label, + 'data-label' => $label, 'class' => 'multipoint vector', 'fill' => 'white', 'stroke' => sprintf('#%02x%02x%02x', ...$color), diff --git a/src/Gis/GisMultiPolygon.php b/src/Gis/GisMultiPolygon.php index 25fda11fa7..3de2cf8f8e 100644 --- a/src/Gis/GisMultiPolygon.php +++ b/src/Gis/GisMultiPolygon.php @@ -194,7 +194,7 @@ class GisMultiPolygon extends GisGeometry public function prepareRowAsSvg(string $spatial, string $label, array $color, ScaleData $scaleData): string { $polygonOptions = [ - 'name' => $label, + 'data-label' => $label, 'class' => 'multipolygon vector', 'stroke' => 'black', 'stroke-width' => 0.5, diff --git a/src/Gis/GisPoint.php b/src/Gis/GisPoint.php index 1771dcc4ed..43bb6221a3 100644 --- a/src/Gis/GisPoint.php +++ b/src/Gis/GisPoint.php @@ -160,7 +160,7 @@ class GisPoint extends GisGeometry public function prepareRowAsSvg(string $spatial, string $label, array $color, ScaleData $scaleData): string { $pointOptions = [ - 'name' => $label, + 'data-label' => $label, 'id' => $label . $this->getRandomId(), 'class' => 'point vector', 'fill' => 'white', diff --git a/src/Gis/GisPolygon.php b/src/Gis/GisPolygon.php index a844d1fced..c44bc0afa5 100644 --- a/src/Gis/GisPolygon.php +++ b/src/Gis/GisPolygon.php @@ -163,7 +163,7 @@ class GisPolygon extends GisGeometry public function prepareRowAsSvg(string $spatial, string $label, array $color, ScaleData $scaleData): string { $polygonOptions = [ - 'name' => $label, + 'data-label' => $label, 'id' => $label . $this->getRandomId(), 'class' => 'polygon vector', 'stroke' => 'black', diff --git a/src/Gis/GisVisualization.php b/src/Gis/GisVisualization.php index 0feef33ef8..815a692da0 100644 --- a/src/Gis/GisVisualization.php +++ b/src/Gis/GisVisualization.php @@ -19,6 +19,7 @@ use TCPDF; use function assert; use function count; +use function htmlspecialchars; use function is_string; use function max; use function mb_strlen; @@ -508,7 +509,7 @@ class GisVisualization $label = trim((string) ($row[$this->labelColumn] ?? '')); if ($format === 'svg') { - $svg .= $gisObj->prepareRowAsSvg($wkt, $label, $color, $scaleData); + $svg .= $gisObj->prepareRowAsSvg($wkt, htmlspecialchars($label), $color, $scaleData); } elseif ($format === 'png') { assert($renderer instanceof ImageWrapper); $gisObj->prepareRowAsPng($wkt, $label, $color, $scaleData, $renderer); diff --git a/src/InsertEdit.php b/src/InsertEdit.php index 82e02752a4..2a947f643d 100644 --- a/src/InsertEdit.php +++ b/src/InsertEdit.php @@ -387,7 +387,7 @@ class InsertEdit * @todo clarify the meaning of the "textfield" class and explain * why character columns have the "char" class instead */ - $theClass = 'char charField'; + $theClass = 'charField'; $textAreaRows = $this->config->settings['CharTextareaRows']; $textareaCols = $this->config->settings['CharTextareaCols']; $extractedColumnspec = Util::extractColumnSpec($column->type); diff --git a/tests/unit/Gis/GisGeometryCollectionTest.php b/tests/unit/Gis/GisGeometryCollectionTest.php index 3ffd7d3d9d..8a7a3e3ac3 100644 --- a/tests/unit/Gis/GisGeometryCollectionTest.php +++ b/tests/unit/Gis/GisGeometryCollectionTest.php @@ -380,7 +380,7 @@ class GisGeometryCollectionTest extends GisGeomTestCase [176, 46, 224], new ScaleData(offsetX: 12, offsetY: 69, scale: 2, height: 150), '', ], diff --git a/tests/unit/Gis/GisLineStringTest.php b/tests/unit/Gis/GisLineStringTest.php index 080cb42395..9105043bc6 100644 --- a/tests/unit/Gis/GisLineStringTest.php +++ b/tests/unit/Gis/GisLineStringTest.php @@ -251,7 +251,7 @@ class GisLineStringTest extends GisGeomTestCase [176, 46, 224], new ScaleData(offsetX: 12, offsetY: 69, scale: 2, height: 150), '', ], ]; diff --git a/tests/unit/Gis/GisMultiLineStringTest.php b/tests/unit/Gis/GisMultiLineStringTest.php index 7bbfeed640..409f3233a3 100644 --- a/tests/unit/Gis/GisMultiLineStringTest.php +++ b/tests/unit/Gis/GisMultiLineStringTest.php @@ -258,10 +258,10 @@ class GisMultiLineStringTest extends GisGeomTestCase 'svg', [176, 46, 224], new ScaleData(offsetX: 12, offsetY: 69, scale: 2, height: 150), - '', ], ]; diff --git a/tests/unit/Gis/GisMultiPointTest.php b/tests/unit/Gis/GisMultiPointTest.php index 5cf2ce6804..db59bcf948 100644 --- a/tests/unit/Gis/GisMultiPointTest.php +++ b/tests/unit/Gis/GisMultiPointTest.php @@ -237,15 +237,15 @@ class GisMultiPointTest extends GisGeomTestCase 'svg', [176, 46, 224], new ScaleData(offsetX: 12, offsetY: 69, scale: 2, height: 150), - '', ], diff --git a/tests/unit/Gis/GisMultiPolygonTest.php b/tests/unit/Gis/GisMultiPolygonTest.php index d1cf239a40..403ec510b9 100644 --- a/tests/unit/Gis/GisMultiPolygonTest.php +++ b/tests/unit/Gis/GisMultiPolygonTest.php @@ -349,10 +349,12 @@ class GisMultiPolygonTest extends GisGeomTestCase [176, 46, 224], new ScaleData(offsetX: -50, offsetY: -50, scale: 2, height: 400), '', ], ]; diff --git a/tests/unit/Gis/GisPolygonTest.php b/tests/unit/Gis/GisPolygonTest.php index d3bcd8fe80..54c73d7ec4 100644 --- a/tests/unit/Gis/GisPolygonTest.php +++ b/tests/unit/Gis/GisPolygonTest.php @@ -254,7 +254,8 @@ class GisPolygonTest extends GisGeomTestCase 'svg', [176, 46, 224], new ScaleData(offsetX: 12, offsetY: 69, scale: 2, height: 150), - '', ], diff --git a/tests/unit/InsertEditTest.php b/tests/unit/InsertEditTest.php index e139257d11..ca7953deb6 100644 --- a/tests/unit/InsertEditTest.php +++ b/tests/unit/InsertEditTest.php @@ -611,7 +611,7 @@ class InsertEditTest extends AbstractTestCase $result = $this->parseString($result); self::assertStringContainsString( - '',