<?php
		

/**
 * Add/fix some accessibility for LimeSurvey
 *
 * @author Alexandre Landry <forXcodeur@gmail.com>
 * @license GPL v3
 * @version 1.0.0
 *
 * @BasedOn : https://git.framasoft.org/SondagePro-LimeSurvey-plugin/moreAccessibility
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */
class patchAccessibility extends PluginBase
{
    protected $storage = 'DbStorage';

    static protected $name = 'patchAccessibility';
    static protected $description = 'Update HTML for question for better labelling, and other accessibility. Connecting radio button/checkbox to label where "other" option is visible.';

    protected $settings = array(
        'updateCheckboxOther' => array(
            'type' => 'select',
            'options'=>array(
                0=> 'No',
                1=> 'Yes'
            ),
            'default'=>1,
            'label' => 'Update checkbox where "Other" option enable. Connecting label to checkbox and connecting textbox to label.'
        ),
        'updateRadioButtonOther' => array(
            'type' => 'select',
            'options'=>array(
                0=> 'No',
                1=> 'Yes'
            ),
            'default'=>1,
            'label' => 'Update radio button where "Other" option enable. Connecting textbox to label and remove unused label.'
        ),
    );   
   
    public function __construct(PluginManager $manager, $id) {
        parent::__construct($manager, $id);
        $this->subscribe('beforeQuestionRender','questionCheckboxLabelOther');        
		$this->subscribe('beforeQuestionRender','questionRadioButtonLabelOther');        
    }

    /*
     * 
     * Description : On checkbox list, when the "other" option is activated, make some change for accessibility.
     * 
     * The label should target the checkbox.
     * The textbox should link to label by aria
     * 
     */
    public function questionCheckboxLabelOther()
    {
	
		if(!$this->get('updateCheckboxOther'))
            return;
			
        $oEvent=$this->getEvent();
        $sType=$oEvent->get('type');
								 
        if(in_array($sType,array(               		
            "M", // Input Checkbox List
            )))
        {
		
			if (strpos( $oEvent->get('answers'), "othercbox") > 0) {	//validate if other is activated
		
				$answerId = "answer"
								.$oEvent->get('surveyId')
								."X".$oEvent->get('gid')
								."X".$oEvent->get('qid');
			
				$textbox_id = 	$answerId
								."other";
								
				$checkbox_id = 	$answerId
								."othercbox";

				$label_id = 	$answerId
								."otherLabel";
						
				$oEvent->set('answers',str_replace('for="'.$textbox_id.'"','for="'.$checkbox_id.'"',$oEvent->get('answers')));	//replace the label For id, pointing to the checkbox instead of the textbox			
				
				$oEvent->set('answers',str_replace('for="'.$checkbox_id.'"','for="'.$checkbox_id.'" id="'.$label_id.'" ',$oEvent->get('answers')));	//add an id to the label
		
				$oEvent->set('answers',str_replace('id="'.$textbox_id.'"','id="'.$textbox_id.'" aria-labelledby="'.$label_id.'" ',$oEvent->get('answers')));	//adding an aria-labelledby to link textbox to the label (by his new id)
				
			}
        }	
    }
  
    /*
     *
     * Description : On radio button list, when the "other" option is activated, make some change for accessibility.
     *
     * The label should target the radio button.
     * The textbox should link to label by aria
     * There's a label around the textbox that shouldn't be there
     * The aria cause multiple read, we need to remove the title of the textbox
     *
     */
	public function questionRadioButtonLabelOther()
    {
	
		if(!$this->get('updateRadioButtonOther'))
            return;			
	
        $oEvent=$this->getEvent();
        $sType=$oEvent->get('type');						
				 
        if(in_array($sType,array(
            "L", // Radio Button List     			            
            )))
        {		
			if (strpos( $oEvent->get('answers'), 'id="SOTH') > 0) {	//validate if other is activated
			
				$id = 	$oEvent->get('surveyId')
						."X".$oEvent->get('gid')
						."X".$oEvent->get('qid');			
			
				$answerId = "answer" 
							.$id;							
			
				$textbox_id = 	$answerId
								."othertext";
								
				$radio_id = 	"SOTH"
								.$id;								

				$label_id = 	$answerId
								."otherLabel";

				$label_textbox_for = 	$textbox_id;							
								
				$label_textbox_html = 	'<label for="'.$label_textbox_for.'">';
							
				
				//We need to remove the label around the textbox
				$firstLabelPos = strpos($oEvent->get('answers'),$label_textbox_html);
				if($firstLabelPos>0)	//if there's no label we dont continue, "Other" is not activated.
				{
					//TODO: change this part into regex
					//TODO: manage label inside label (future version possible error)
					//We remove the label around the textbox
					$sideB = substr($oEvent->get('answers'),$firstLabelPos + strlen($label_textbox_html) );
					$firstLabelPos2 = strpos($sideB,'</label>');
					
					//TODO: change this part into regex
					//we remove the title of the textbox
					$textbox = substr($sideB,0,$firstLabelPos2); //get the textbox code
								
					$textbox = preg_replace('/'.preg_quote('title="').'.*?'.preg_quote('"') . '/', '', $textbox); //remove title					
														
					$result = 	substr($oEvent->get('answers'),0,$firstLabelPos-1)
								.$textbox
								.substr($sideB,$firstLabelPos2+strlen('</label>'));						
					$oEvent->set('answers',$result);	//the new answer without label around textbox
					
					$oEvent->set('answers',str_replace('for="'.$radio_id.'"','for="'.$radio_id.'" id="'.$label_id.'" ',$oEvent->get('answers')));	//add an id to the label
		
					$oEvent->set('answers',str_replace('id="'.$textbox_id.'"','id="'.$textbox_id.'" aria-labelledby="'.$label_id.'" ',$oEvent->get('answers')));	//adding an aria-labelledby to link textbox to the label (by his new id)										
		

				}
			}			
        }	
    }
  
}
