Display an icon to split or join two pages of the quiz.

@param structure $structure object containing the structure of the quiz.
@param int $slot the first slot on the page we are outputting.
@return string HTML to output.
356444
public function page_split_join_button($structure, $slot) {
        $insertpagebreak = !$structure->is_last_slot_on_page($slot);
        $url = new \moodle_url('repaginate.php', array('quizid' => $structure->get_quizid(),
                'slot' => $slot, 'repag' => $insertpagebreak ? 2 : 1, 'sesskey' => sesskey()));

        if ($insertpagebreak) {
            $title = get_string('addpagebreak', 'quiz');
            $image = $this->image_icon('e/insert_page_break', $title);
            $action = 'addpagebreak';
        } else {
            $title = get_string('removepagebreak', 'quiz');
            $image = $this->image_icon('e/remove_page_break', $title);
            $action = 'removepagebreak';
        }

        // Disable the link if quiz has attempts.
        $disabled = null;
        if (!$structure->can_be_edited()) {
            $disabled = 'disabled';
        }
        return html_writer::span($this->action_link($url, $image, null, array('title' => $title,
                    'class' => 'page_split_join cm-edit-action', 'disabled' => $disabled, 'data-action' => $action)),
                'page_split_join_wrapper');
    }
1173116
private static function printStructureLine($key, $value, Structure $structure, $maxKeyLength, $maxValueLength)
    {
        $result    = '';
        $insertTab = ($structure->getTab()) ? true : false;
        $border    = $structure->getBorder();

        if ($border) {
            $keyLength        = Util::getVisibleStringLength($key);
            $missingKeyLength = $maxKeyLength - $keyLength;
            $fillingKeySpace  = Util::buildPatternLine(' ', $missingKeyLength);

            $valueLength        = Util::getVisibleStringLength($value);
            $missingValueLength = $maxValueLength - $valueLength;
            $fillingValueSpace  = Util::buildPatternLine(' ', $missingValueLength);

            $result .= ($insertTab ? $structure->getTab() : '');
            $result .= $border->getColumnCharacter() . ' ' . $key . $fillingKeySpace . ' ';
            $result .= $structure->getKeyToValueCharacter() . ' ' . $value . $fillingValueSpace . ' ';
            $result .= $border->getColumnCharacter() . PHP_EOL;
        } else {
            $keyLength        = Util::getVisibleStringLength($key);
            $missingKeyLength = $maxKeyLength - $keyLength;
            $fillingKeySpace  = Util::buildPatternLine(' ', $missingKeyLength);

            $result .= ($insertTab ? $structure->getTab() : '');
            $result .= $key . $fillingKeySpace . ' ';
            $result .= $structure->getKeyToValueCharacter() . ' ' . $value;
            $result .= PHP_EOL;
        }

        return $result;
    }
544928
public function query($query, $structure = null)
	{
		// Check the type of query to decide what to return
		list($type) = explode(' ', $query, 2);
		$type       = strtolower($type);

		// Default structure if needed
		if ($type == 'select' && is_null($structure))
		{
			$structure = 'rows';
		}

		$this->connection->prepare($query)->bind($this->syntax->getBindings());

		$result = (isset($structure))
		        ? $this->connection->{constant('self::' . strtoupper($structure))}()
		        : $this->connection->query();

		return $result;
	}
1116978
private function buildSelectForStructure($locale, StructureInterface $structure, &$names)
    {
        $nodeNameProperty = $structure->getProperty('title');
        $result = '';

        $name = $this->getTranslatedProperty($nodeNameProperty, $locale)->getName();
        if (!in_array($name, $names)) {
            $names[] = $name;
            $result .= ', ' . $this->buildSelector($name);
        }

        if ($structure->hasTag('sulu.rlp')) {
            $urlProperty = $structure->getPropertyByTagName('sulu.rlp');
            $name = $this->getTranslatedProperty($urlProperty, $locale)->getName();

            if ('resource_locator' !== $urlProperty->getContentTypeName() && !in_array($name, $names)) {
                $names[] = $name;
                $result .= ', ' . $this->buildSelector($name);
            }
        }

        return $result;
    }
189832
protected function guessNode($slot)
    {
        if (isset($this->slotsMap[$slot])) {
            return $this->slotsMap[$slot];
        }

        $count = \count($this->hosts);
        $index = \min((int) ($slot / (int) (16384 / $count)), $count - 1);
        $nodes = \array_values($this->hosts);

        return $nodes[$index];
    }
70871
public function maximum_grade_input($structure, \moodle_url $pageurl) {
        $output = '';
        $output .= html_writer::start_div('maxgrade');
        $output .= html_writer::start_tag('form', array('method' => 'post', 'action' => 'edit.php',
                'class' => 'quizsavegradesform form-inline'));
        $output .= html_writer::start_tag('fieldset', array('class' => 'invisiblefieldset'));
        $output .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey()));
        $output .= html_writer::input_hidden_params($pageurl);
        $output .= html_writer::tag('label', get_string('maximumgrade') . ' ',
                array('for' => 'inputmaxgrade'));
        $output .= html_writer::empty_tag('input', array('type' => 'text', 'id' => 'inputmaxgrade',
                'name' => 'maxgrade', 'size' => ($structure->get_decimal_places_for_grades() + 2),
                'value' => $structure->formatted_quiz_grade(),
                'class' => 'form-control'));
        $output .= html_writer::empty_tag('input', array('type' => 'submit', 'class' => 'btn btn-secondary ml-1',
                'name' => 'savechanges', 'value' => get_string('save', 'quiz')));
        $output .= html_writer::end_tag('fieldset');
        $output .= html_writer::end_tag('form');
        $output .= html_writer::end_tag('div');
        return $output;
    }
166957
private function outputWebspacePageTemplates(Webspace $webspace)
    {
        $this->output->writeln('Page Templates:');

        $structures = $this->structureManager->getStructures();

        $checkedTemplates = [];

        foreach ($webspace->getDefaultTemplates() as $template) {
            $checkedTemplates[] = $template;
        }

        foreach ($structures as $structure) {
            $template = $structure->getKey();

            if (!$structure->getInternal() && !in_array($template, $checkedTemplates)) {
                $this->validatePageTemplate('page', $structure->getKey());
            }
        }
    }
1240716
public function save( & $structure )
    {
        if ( is_object( $structure ) )
        {
            $section    = $structure->section;
            $settings   = (array) $structure->settings;
        }
        else if ( is_array( $structure ) )
        {
            $section    = $structure['section'];
            $settings   = (array) $structure['settings'];
        }
        else
        {
            return 0;
        }

        $rows   = 0;
        $set    = array();
        $rem    = array();
        $def    = $this->getDefinitions();
        $elems  = $def->getElements( $section );
        $fields = $def->getFieldsets( $section );

        if ( ! empty( $fields ) && ! empty( $settings ) )
        {
            foreach ( $fields as $name => $fieldset )
            {
                if ( isset( $settings[$name] ) )
                {
                    if ( $settings[$name] instanceof StructureAbstract )
                    {
                        $fieldsetSettings = $settings[$name]->settings;
                    }
                    else if ( is_array( $settings[$name] ) )
                    {
                        if ( array_key_exists( 'settings', $settings[$name] ) )
                        {
                            $fieldsetSettings = $settings[$name]['settings'];
                        }
                        else
                        {
                            $fieldsetSettings = $settings[$name];
                        }
                    }
                    else
                    {
                        continue;
                    }

                    $subSection = array(
                        'section'   => $fieldset,
                        'settings'  => $fieldsetSettings,
                    );

                    $rows += $this->save( $subSection );
                }
            }
        }

        if ( ! empty( $elems ) && ! empty( $settings ) )
        {
            foreach ( $elems as $name => $spec )
            {
                if ( isset( $settings[$name] ) )
                {
                    if ( is_scalar( $settings[$name] ) )
                    {
                        $set[$spec['key']] = array(
                            'value' => $settings[$name],
                            'type'  => empty( $spec['type'] )
                                    ? 'ini' : $spec['type'],
                        );
                    }
                    else
                    {
                        $rem[] = $spec['key'];
                        foreach ( $settings[$name] as $index => $value )
                        {
                            $set[$spec['key'] . '.' . $index] = array(
                                'value' => $value,
                                'type'  => empty( $spec['type'] )
                                        ? 'ini' : $spec['type'],
                            );
                        }
                    }
                }
                else
                {
                    $rem[] = $spec['key'];
                }
            }
        }

        $connection = $this->getDbAdapter()
                           ->getDriver()
                           ->getConnection();

        $connection->beginTransaction();

        try
        {
            if ( ! empty( $rem ) )
            {
                $delete = $this->sql()
                               ->delete()
                               ->where( $this->keysWhere( $rem ) );

                $result = $this->sql()
                               ->prepareStatementForSqlObject( $delete )
                               ->execute();

                $rows += $result->getAffectedRows();
            }

            foreach ( $set as $key => $spec )
            {
                $type  = $spec['type'];
                $value = $spec['value'];

                $update = $this->sql()
                               ->update()
                               ->set( array(
                                   'value'  => $value,
                               ) )
                               ->where( array(
                                   'key'    => $key,
                                   'type'   => $type,
                               ) );

                $result = $this->sql()
                               ->prepareStatementForSqlObject( $update )
                               ->execute();

                $updateRows = $result->getAffectedRows();

                if ( $updateRows )
                {
                    $rows += $updateRows;
                }
                else
                {
                    $insert = $this->sql()
                                   ->insert()
                                   ->values( array(
                                       'key'    => $key,
                                       'type'   => $type,
                                       'value'  => $value,
                                   ) );

                    $result = $this->sql()
                                   ->prepareStatementForSqlObject( $insert )
                                   ->execute();

                    $rows += $result->getAffectedRows();
                }
            }

            $connection->commit();
        }
        catch ( \Exception $ex )
        {
            $connection->rollback();
            throw $ex;
        }

        return $rows;
    }
891319
protected function parseHeader($structure, $document)
    {
        $elements = array();
        $count    = count($structure);

        for ($position = 0; $position < $count; $position += 2) {
            $name  = $structure[$position][1];
            $type  = $structure[$position + 1][0];
            $value = $structure[$position + 1][1];

            $elements[$name] = $this->parseHeaderElement($type, $value, $document);
        }

        return new Header($elements, $document);
    }
1158149
protected function repaginate_button(structure $structure, \moodle_url $pageurl) {
        $header = html_writer::tag('span', get_string('repaginatecommand', 'quiz'), array('class' => 'repaginatecommand'));
        $form = $this->repaginate_form($structure, $pageurl);

        $buttonoptions = array(
            'type'  => 'submit',
            'name'  => 'repaginate',
            'id'    => 'repaginatecommand',
            'value' => get_string('repaginatecommand', 'quiz'),
            'class' => 'btn btn-secondary mb-1',
            'data-header' => $header,
            'data-form'   => $form,
        );
        if (!$structure->can_be_repaginated()) {
            $buttonoptions['disabled'] = 'disabled';
        } else {
            $this->page->requires->js_call_amd('mod_quiz/repaginate', 'init');
        }

        return html_writer::empty_tag('input', $buttonoptions);
    }
1287321
public function toOutput($structure, $assoc = true)
    {
        switch ($structure) {
            case 'string':
                $output = $this->toString();
                break;
            case 'array':
            default:
                $output = $this->toArray($assoc);
                break;
        }
        return $output;
    }
436679
protected function templateLink($title, $link = null, $icon = null)
    {
        if (!isset($link)) {
            return '<span>' . $icon . $title . '</span>';
        }
        return '<a title="' . $title . '" href="' . $link . '">' . $icon . $title . '</a>';
    }
535445
public function quiz_state_warnings(structure $structure) {
        $warnings = $structure->get_edit_page_warnings();

        if (empty($warnings)) {
            return '';
        }

        $output = array();
        foreach ($warnings as $warning) {
            $output[] = \html_writer::tag('p', $warning);
        }
        return $this->box(implode("\n", $output), 'statusdisplay');
    }
890039
protected function selectmultiple_controls(structure $structure) {
        $output = '';

        // Bulk action button delete and bulk action button cancel.
        $buttondeleteoptions = array(
            'type' => 'button',
            'id' => 'selectmultipledeletecommand',
            'value' => get_string('deleteselected', 'mod_quiz'),
            'class' => 'btn btn-secondary'
        );
        $buttoncanceloptions = array(
            'type' => 'button',
            'id' => 'selectmultiplecancelcommand',
            'value' => get_string('cancel', 'moodle'),
            'class' => 'btn btn-secondary'
        );

        $groupoptions = array(
            'class' => 'btn-group selectmultiplecommand actions',
            'role' => 'group'
        );

        $output .= html_writer::tag('div',
                        html_writer::tag('button', get_string('deleteselected', 'mod_quiz'), $buttondeleteoptions) .
                        " " .
                        html_writer::tag('button', get_string('cancel', 'moodle'),
                $buttoncanceloptions), $groupoptions);

        $toolbaroptions = array(
            'class' => 'btn-toolbar',
            'role' => 'toolbar',
            'aria-label' => get_string('selectmultipletoolbar', 'quiz'),
        );

        // Select all/deselect all questions.
        $buttonselectalloptions = array(
            'role' => 'button',
            'id' => 'questionselectall',
            'class' => 'btn btn-link'
        );
        $buttondeselectalloptions = array(
            'role' => 'button',
            'id' => 'questiondeselectall',
            'class' => 'btn btn-link'
        );
        $output .= html_writer::tag('div',
                html_writer::tag('div',
                        html_writer::link('#', get_string('selectall', 'quiz'), $buttonselectalloptions) .
                        html_writer::tag('span', "/", ['class' => 'separator']) .
                        html_writer::link('#', get_string('selectnone', 'quiz'), $buttondeselectalloptions),
                        array('class' => 'btn-group selectmultiplecommandbuttons')),
                $toolbaroptions);
        return $output;
    }
633719
public function marked_out_of_field(structure $structure, $slot) {
        if (!$structure->is_real_question($slot)) {
            $output = html_writer::span('',
                    'instancemaxmark decimalplaces_' . $structure->get_decimal_places_for_question_marks());

            $output .= html_writer::span(
                    $this->pix_icon('spacer', '', 'moodle', array('class' => 'editicon visibleifjs', 'title' => '')),
                    'editing_maxmark');
            return html_writer::span($output, 'instancemaxmarkcontainer infoitem');
        }

        $output = html_writer::span($structure->formatted_question_grade($slot),
                'instancemaxmark decimalplaces_' . $structure->get_decimal_places_for_question_marks(),
                array('title' => get_string('maxmark', 'quiz')));

        $output .= html_writer::span(
            html_writer::link(
                new \moodle_url('#'),
                $this->pix_icon('t/editstring', '', 'moodle', array('class' => 'editicon visibleifjs', 'title' => '')),
                array(
                    'class' => 'editing_maxmark',
                    'data-action' => 'editmaxmark',
                    'title' => get_string('editmaxmark', 'quiz'),
                )
            )
        );
        return html_writer::span($output, 'instancemaxmarkcontainer');
    }
143924
protected function start_section($structure, $section) {

        $output = '';

        $sectionstyle = '';
        if ($structure->is_only_one_slot_in_section($section)) {
            $sectionstyle = ' only-has-one-slot';
        }

        $output .= html_writer::start_tag('li', array('id' => 'section-'.$section->id,
            'class' => 'section main clearfix'.$sectionstyle, 'role' => 'region',
            'aria-label' => $section->heading));

        $output .= html_writer::start_div('content');

        $output .= html_writer::start_div('section-heading');

        $headingtext = $this->heading(html_writer::span(
                html_writer::span($section->heading, 'instancesection'), 'sectioninstance'), 3);

        if (!$structure->can_be_edited()) {
            $editsectionheadingicon = '';
        } else {
            $editsectionheadingicon = html_writer::link(new \moodle_url('#'),
                $this->pix_icon('t/editstring', get_string('sectionheadingedit', 'quiz', $section->heading),
                        'moodle', array('class' => 'editicon visibleifjs')),
                        array('class' => 'editing_section', 'data-action' => 'edit_section_title'));
        }
        $output .= html_writer::div($headingtext . $editsectionheadingicon, 'instancesectioncontainer');

        if (!$structure->is_first_section($section) && $structure->can_be_edited()) {
            $output .= $this->section_remove_icon($section);
        }
        $output .= $this->section_shuffle_questions($structure, $section);

        $output .= html_writer::end_div($output, 'section-heading');

        return $output;
    }
1198714
public function question_move_icon(structure $structure, $slot) {
        return html_writer::link(new \moodle_url('#'),
            $this->pix_icon('i/dragdrop', get_string('move'), 'moodle', array('class' => 'iconsmall', 'title' => '')),
            array('class' => 'editing_move', 'data-action' => 'move')
        );
    }