From 751179a592a92cfd8872727c126f03403e13dadf Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Thu, 23 May 2019 16:48:11 -0500 Subject: [PATCH] Apply bugfix patches from issues 29, 30, 31, 32, 33, 34, and 35 see: https://code.google.com/archive/p/quail-lib/issues/29 see: https://code.google.com/archive/p/quail-lib/issues/30 see: https://code.google.com/archive/p/quail-lib/issues/31 see: https://code.google.com/archive/p/quail-lib/issues/32 see: https://code.google.com/archive/p/quail-lib/issues/33 see: https://code.google.com/archive/p/quail-lib/issues/34 see: https://code.google.com/archive/p/quail-lib/issues/35 --- quail/common/accessibility_tests.php | 65 ++++++++++++++++++++++++++++++++---- quail/common/css.php | 15 ++++++--- quail/common/test.php | 22 +++++++++--- quail/guidelines/translations/en.txt | 8 ++--- 4 files changed, 90 insertions(+), 20 deletions(-) diff --git a/quail/common/accessibility_tests.php b/quail/common/accessibility_tests.php index 04b9b19..8efe5b3 100755 --- a/quail/common/accessibility_tests.php +++ b/quail/common/accessibility_tests.php @@ -1138,7 +1138,7 @@ class cssTextHasContrast extends quailColorTest { $background = (isset($style['background-color'])) ? $style['background-color'] : $style['background']; - if(!$background || $this->options['css_only_use_default']) { + if(!$background || (isset($this->options['css_only_use_default']) && $this->options['css_only_use_default'])) { $background = $this->default_background; } $luminosity = $this->getLuminosity( @@ -2238,7 +2238,7 @@ class formWithRequiredLabel extends quailTest { } if($k) { foreach($this->suspect_styles as $style) { - if($styles[$k][$style] != $styles[($k - 1)][$style]) { + if(isset($styles[$k][$style]) && $styles[$k][$style] != $styles[($k - 1)][$style]) { $form = $this->getElementAncestor($label, 'form'); if($form) { $this->addReport($form); @@ -4543,8 +4543,8 @@ class pNotUsedAsHeader extends quailTest { */ function check() { foreach($this->getAllElements('p') as $p) { - if(($p->nodeValue == $p->firstChild->nodeValue) && - is_object($p->firstChild) && + if (is_object($p->firstChild) && + ($p->nodeValue == $p->firstChild->nodeValue) && property_exists($p->firstChild, 'tagName') && in_array($p->firstChild->tagName, $this->head_tags)) { $this->addReport($p); @@ -4552,7 +4552,7 @@ class pNotUsedAsHeader extends quailTest { } else { $style = $this->css->getStyle($p); - if($style['font-weight'] == 'bold') { + if(isset($style['font-weight']) && $style['font-weight'] == 'bold') { $this->addReport($p); } } @@ -5266,6 +5266,18 @@ class tableHeaderLabelMustBeTerse extends quailTableTest { } } } + else if($this->propertyIsEqual($child, 'tagName', 'tbody')) { + foreach ($child->childNodes as $tbody_child){ + if($this->propertyIsEqual($tbody_child, 'tagName', 'tr')) { + foreach($tbody_child->childNodes as $td) { + if($this->propertyIsEqual($td, 'tagName', 'th')) { + if(strlen($td->getAttribute('abbr')) > 20) + $this->addReport($td); + } + } + } + } + } } } @@ -5388,6 +5400,15 @@ class tableLayoutHasNoSummary extends quailTableTest { $this->addReport($table); $first_row = false; } + else if($this->propertyIsEqual($child, 'tagName', 'tbody') && $first_row) { + foreach($child->childNodes as $tbody_child) { + if($this->propertyIsEqual($tbody_child, 'tagName', 'tr') && $first_row) { + if(!$this->elementHasChild($tbody_child, 'th')) + $this->addReport($table); + $first_row = false; + } + } + } } } } @@ -5639,11 +5660,28 @@ class tableWithBothHeadersUseScope extends quailTest { } else { foreach($child->childNodes as $td) { + if (!property_exists($td, 'tagName')) continue; if($td->tagName == 'th' && !$td->hasAttribute('scope')) $fail = true; } } } + else if($this->propertyIsEqual($child, 'tagName', 'tbody')) { + foreach($child->childNodes as $tbody_child) { + if($this->propertyIsEqual($tbody_child, 'tagName', 'tr')) { + if($this->propertyIsEqual($tbody_child->firstChild, 'tagName', 'td')) { + if(!$tbody_child->firstChild->hasAttribute('scope')) + $fail = true; + } + foreach($tbody_child->childNodes as $td) { + if(property_exists($td, 'tagName')){ + if($td->tagName == 'th' && !$td->hasAttribute('scope')) + $fail = true; + } + } + } + } + } } if($fail) $this->addReport($table); @@ -5681,7 +5719,20 @@ class tableWithMoreHeadersUseID extends quailTableTest { if($row > 1) $multi_headers = true; } - + } + } + else if($this->propertyIsEqual($child, 'tagName', 'tbody')) { + foreach($child->childNodes as $tbody_child) { + if($this->propertyIsEqual($tbody_child, 'tagName', 'tr')) { + $row ++; + foreach($tbody_child->childNodes as $cell) { + if($this->propertyIsEqual($cell, 'tagName', 'th')) { + $th[] = $cell; + if($row > 1) + $multi_headers = true; + } + } + } } } } @@ -6039,4 +6090,4 @@ class textIsNotSmall extends quailTest { } -/*@}*/ \ No newline at end of file +/*@}*/ diff --git a/quail/common/css.php b/quail/common/css.php index f286195..58770dd 100644 --- a/quail/common/css.php +++ b/quail/common/css.php @@ -123,7 +123,7 @@ class quailCSS { foreach($this->css as $selector => $style) { $xpath = new DOMXPath($this->dom); $entries = @$xpath->query($this->getXpath($selector)); - if($entries->length) { + if(is_object($entries) && property_exists($entries, 'length') && $entries->length) { foreach($entries as $e) { if(!$e->hasAttribute('quail_style_index')) { $e->setAttribute('quail_style_index', $this->next_index); @@ -149,10 +149,16 @@ class quailCSS { */ private function addCSSToElement($element, $style, $specificity) { $index_id = $element->getAttribute('quail_style_index'); + if (!isset($this->style_index[$index_id])){ + $this->style_index[$index_id] = array(); + } + foreach($style as $name => $value) { - if(!$this->style_index[$index_id][$name] || - $this->style_index[$index_id][$name]['specificity'] < $specificity - || strpos($value, '!important') !== false) + if(!isset($this->style_index[$index_id][$name]) || + !$this->style_index[$index_id][$name] || + (isset($this->style_index[$index_id][$name]['specificity']) && + $this->style_index[$index_id][$name]['specificity'] < $specificity) || + strpos($value, '!important') !== false) { $this->style_index[$index_id][$name] = array( 'value' => str_replace('!important', '', trim(strtolower($value))), @@ -264,6 +270,7 @@ class quailCSS { $inline_styles = explode(';', $element->getAttribute('style')); foreach($inline_styles as $inline_style) { $s = explode(':', $inline_style); + if (!isset($s[1])) continue; $style[$s[0]] = trim(strtolower($s[1])); } } diff --git a/quail/common/test.php b/quail/common/test.php index 99a6aff..7157a02 100644 --- a/quail/common/test.php +++ b/quail/common/test.php @@ -513,10 +513,22 @@ class quailTableTest extends quailTest { if($table->tagName != 'table') return false; foreach($table->childNodes as $child) { - if(property_exists($child, 'tagName') && $child->tagName == 'tr') { - foreach($child->childNodes as $row_child) { - if(property_exists($row_child, 'tagName') && $row_child->tagName == 'th') - return true; + if(property_exists($child, 'tagName')){ + if ($child->tagName == 'tr') { + foreach($child->childNodes as $row_child) { + if(property_exists($row_child, 'tagName') && $row_child->tagName == 'th') + return true; + } + } + else if ($child->tagName == 'tbody') { + foreach($child->childNodes as $tbody_child) { + if (property_exists($tbody_child, 'tagName') && $tbody_child->tagName == 'tr') { + foreach($tbody_child->childNodes as $row_child) { + if(property_exists($row_child, 'tagName') && $row_child->tagName == 'th') + return true; + } + } + } } } if(property_exists($child, 'tagName') && $child->tagName == 'thead') @@ -987,4 +999,4 @@ class bodyColorContrast extends quailColorTest { if( $this->getLuminosity($body->getAttribute($this->foreground), $body->getAttribute($this->background)) < 5) $this->addReport(null, null, false); } -} \ No newline at end of file +} diff --git a/quail/guidelines/translations/en.txt b/quail/guidelines/translations/en.txt index 9889ee9..874368a 100644 --- a/quail/guidelines/translations/en.txt +++ b/quail/guidelines/translations/en.txt @@ -1,6 +1,6 @@ "imgHasAlt","Image elements must have an ""alt"" attribute","

All img elements must have an alt attribute

Example

Wrong

<img src=""dog.jpg"">

Right

<img src=""dog.jpg"" alt=""A photograph of a dog"">

","1" "imgAltIsDifferent","Image ""alt"" attributes should not be the same as the filename","

All img elements should have an ""alt"" attribute that is not just the name of the file, unless the filename communicates everything about the file.

Example

Wrong

<img src=""dog.jpg"" alt=""dog.jpg"">

Right

<img src=""dog.jpg"" alt=""A photograph of a dog"">

","1" -"imgAltIsTooLong","Image Alt text is short","

All ""alt"" attributes for img elements should be clear and concise. ""Alt"" attributes over 100 characters long should be reviewed to see if they are too long.

Example

Wrong

<img src=""dog.jpg"" alt=""A photograph of my very, very, very special dog whom I love so much. He is a very good dog, a loving dog, and my constant companion these many years. Yes, all agree, my dog is a good dog."">

Right

<img src=""dog.jpg"" alt=""A photograph of a dog"">

","1" +"imgAltIsTooLong","Image Alt text is too long","

All ""alt"" attributes for img elements should be clear and concise. ""Alt"" attributes over 100 characters long should be reviewed to see if they are too long.

Example

Wrong

<img src=""dog.jpg"" alt=""A photograph of my very, very, very special dog whom I love so much. He is a very good dog, a loving dog, and my constant companion these many years. Yes, all agree, my dog is a good dog."">

Right

<img src=""dog.jpg"" alt=""A photograph of a dog"">

","1" "imgNonDecorativeHasAlt","Any non-decorative images should have a non-empty ""alt"" attribute","

Any image that is not used decorativey or which is purely for layout purposes cannot have an empty ""alt"" attribute.

Example

Wrong

<img src=""dog.jpg"" alt="""">

Right

<img src=""dog.jpg"" alt=""A photograph of a dog"">

","2" "imgImportantNoSpacerAlt","Images that are important should not have a purely white-space ""alt"" attribute","

Any image that is not used decorativey or which is purely for layout purposes cannot have an ""alt"" attribute that consists solely of white space (i.e. a space, or a new line).

Example

Wrong

<img src=""dog.jpg"" alt="" "">

Right

<img src=""dog.jpg"" alt=""A photograph of a dog"">

","1" "imgAltNotPlaceHolder","Images should not have a simple placeholder text as an ""alt"" attribute","

Any image that is not used decorativey or which is purely for layout purposes cannot have an ""alt"" attribute that consists solely of placeholders. Placeholders include:

Example

Wrong

<img src=""dog.jpg"" alt=""image"">

Right

<img src=""dog.jpg"" alt=""A photograph of a dog"">

","1" @@ -31,7 +31,7 @@ "frameTitlesDescribeFunction","All ""frame"" elemetns should have a ""title"" attribute that describes the purpose of the frame","

Each frame elements should have a ""title"" attribute which describes the purpose or function of the frame.

Example

Wrong

<frame src=""navigation.html""></frame>

Right

<frame src=""navigation.html"" title=""The site navigation""></frame>

","3" "frameSrcIsAccessible","The source for each frame is accessible content.","

Each frame should contain accessible content, and contain content accessible to screen readers, like HTML as opposed to an image.

","3" "frameRelationshipsMustBeDescribed","Complex framesets should contain a ""longdesc"" attribute","

If a frameset contains three or more frames, use a ""longdesc"" attribute to help describe the purpose of the frames.

Example

Wrong

<frameset cols=""25%,50%,25%""> <frame src=""frame_1.htm"" /> <frame src=""frame_2.htm"" /> <frame src=""frame_3.htm"" /></frameset>

Right

<frameset cols=""25%,50%,25%"" longdesc=""description.html""> <frame src=""frame_1.htm"" /> <frame src=""frame_2.htm"" /> <frame src=""frame_3.htm"" /></frameset>

","2" -"framesetMustHaveNoFramesSection","All framesets should contain a noframes section","

If a frameset contains three or more frames, use a ""longdesc"" attribute to help describe the purpose of the frames.

Example

Wrong

<frameset cols=""25%,50%,25%""> <frame src=""frame_1.htm"" /> <frame src=""frame_2.htm"" /> <frame src=""frame_3.htm"" /></frameset>

Right

<frameset cols=""25%,50%,25%"" longdesc=""description.html""> <frame src=""frame_1.htm"" /> <frame src=""frame_2.htm"" /> <frame src=""frame_3.htm"" /> <noframes> <body> This is more information for users without frames. It should contain links to all the other frames. </body> </noframes></frameset>

","1" +"framesetMustHaveNoFramesSection","All framesets should contain a noframes section","

If a frameset contains three or more frames, use a ""longdesc"" attribute to help describe the purpose of the frames.

Example

Wrong

<frameset cols=""25%,50%,25%""> <frame src=""frame_1.htm"" /> <frame src=""frame_2.htm"" /> <frame src=""frame_3.htm"" /></frameset>

Right

<frameset cols=""25%,50%,25%"" longdesc=""description.html""> <frame src=""frame_1.htm"" /> <frame src=""frame_2.htm"" /> <frame src=""frame_3.htm"" /> <noframes> <body> This is more information for users without frames. It should contain links to all the other frames. </body> </noframes></frameset>

","1" "noframesSectionMustHaveTextEquivalent","All ""noframes"" elements should contain the text content from all frames","

The noframes content should either replicate or link to the content visible within the frames.

","2" "headerH1","The header following an h1 is h1 or h2","

The header following an h1 element should either be an h2 or another h1.

Users of screen readers often use headers to make sense of the structure of the document, and having headers in the right order can be very helpful. It also helps the document itself to be consistently structured.

","3" @@ -137,7 +137,7 @@ ","2" "linkUsedToDescribeNavigation","Document uses link element to describe navigation if it is within a collection.","The link element can provide metadata about the position of an HTML page within a set of Web units or can assist in locating content with a set of Web units.","1" "linkUsedForAlternateContent","Use a ""link"" element for alternate content","

Documents which contain things like videos, sound, or other forms of media that are not accessible, should provide a link element with a ""rel"" attribute of ""alternate"" in the document header.

Example

<head><link rel=""alternate"" href=""transcription.html""/></head>

","3" -"tableUsesCaption","Data tables should contain a ""caption"" element if not described elsewhere","

Unless otherwise described in the document, tables should contain caption elements to describe the purpose of the table.

Example

A short description of this table
","1" +"tableUsesCaption","Data tables should contain a ""caption"" element if not described elsewhere","

Unless otherwise described in the document, tables should contain caption elements to describe the purpose of the table.

Example

<table><caption>A short description of this table</caption></table>

","1" "tableUsesAbbreviationForHeader","Table headers over 20 characters should provide an ""abbr"" attribute","

For long table headers, use an ""abbr"" attribute that is less than short (less than 20 characters long).

Examples

Wrong

<th>The total number of people who liked chocolate</th>

Right

<th abbr=""Like Chocolate"">The total number of people who liked chocolate</th>

","3" "tableHeaderLabelMustBeTerse","Table header lables must be terse","

The ""abbr"" attribute for table headers must be terse (less than 20 characters long).

","2" "preShouldNotBeUsedForTabularLayout","""Pre"" elements should not be used for tabular data","

If a pre element is used for tabular data, change the data to use a well-formed table.

@@ -236,4 +236,4 @@ "labelsAreAssignedToAnInput","All labels should be associated with an input","

All label elements should be assigned to an input item, and should have a for attribute which equals the id attribute of a form element.

","1" "imgAltTextNotRedundant","Unless the image files are the same, no image should contain redundant alt text","

Every distinct image on a page should have it's own alt text which is different than all the others on the page to avoid redundancy and confusion.

Example

Wrong

<img src="rex.jpg" alt="this is an image of rex"><img src="me.jpg" alt="this is an image of rex">

Right

<img src="rex.jpg" alt="this is an image of rex"><img src="me.jpg" alt="a photo of myself">

","1" "selectJumpMenus","Select jump menus should jump on button press, not on state change","

If you wish to use a 'Jump' menu with a select item that then redirects users to another page, the jump should occur on the user pressing a button, rather than on the change event of that select eleemnt.

","2" -"textIsNotSmall","The text size is not less than 9 pixels high","

To help users with difficulty reading small text, ensure text size is no less than 9 pixels high.

","2" \ No newline at end of file +"textIsNotSmall","The text size is not less than 9 pixels high","

To help users with difficulty reading small text, ensure text size is no less than 9 pixels high.

","2" -- 1.8.3.1