<commit_before><?php

	/**
	 * @package content
	 */
	/**
	 * The Datasource Editor page allows a developer to create new datasources
	 * from the four Symphony types, Section, Authors, Navigation, Dynamic XML,
	 * and Static XML
	 */
	require_once(TOOLKIT . '/class.gateway.php');
	require_once(TOOLKIT . '/class.resourcespage.php');

	Class contentBlueprintsDatasources extends ResourcesPage{

		public $_errors = array();

		public function __viewIndex($resource_type){
			parent::__viewIndex(RESOURCE_TYPE_DS);

			$this->setTitle(__('%1$s &ndash; %2$s', array(__('Data Sources'), __('Symphony'))));
			$this->appendSubheading(__('Data Sources'), Widget::Anchor(__('Create New'), Administration::instance()->getCurrentPageURL().'new/', __('Create a new data source'), 'create button', NULL, array('accesskey' => 'c')));
		}

		// Both the Edit and New pages need the same form
		public function __viewNew(){
			$this->__form();
		}

		public function __viewEdit(){
			$this->__form();
		}

		public function __form(){
			$formHasErrors = (is_array($this->_errors) && !empty($this->_errors));
			if($formHasErrors) {
				$this->pageAlert(
					__('An error occurred while processing this form. See below for details.')
					, Alert::ERROR
				);
			}
			// These alerts are only valid if the form doesn't have errors
			else if(isset($this->_context[2])) {
				switch($this->_context[2]) {
					case 'saved':
						$this->pageAlert(
							__('Data source updated at %s.', array(DateTimeObj::getTimeAgo()))
							. ' <a href="' . SYMPHONY_URL . '/blueprints/datasources/new/" accesskey="c">'
							. __('Create another?')
							. '</a> <a href="' . SYMPHONY_URL . '/blueprints/datasources/" accesskey="a">'
							. __('View all Data sources')
							. '</a>'
							, Alert::SUCCESS);
						break;

					case 'created':
						$this->pageAlert(
							__('Data source created at %s.', array(DateTimeObj::getTimeAgo()))
							. ' <a href="' . SYMPHONY_URL . '/blueprints/datasources/new/" accesskey="c">'
							. __('Create another?')
							. '</a> <a href="' . SYMPHONY_URL . '/blueprints/datasources/" accesskey="a">'
							. __('View all Data sources')
							. '</a>'
							, Alert::SUCCESS);
						break;
				}
			}

			$providers = Symphony::ExtensionManager()->getProvidersOf('data-sources');

			if(isset($_POST['fields'])){
				$fields = $_POST['fields'];
				$fields['paginate_results'] = ($fields['paginate_results'] == 'on') ? 'yes' : 'no';

				if(!in_array($fields['source'], array('authors', 'navigation', 'dynamic_xml', 'static_xml')) && is_array($fields['filter']) && !empty($fields['filter'])){
					$filters = array();
					foreach($fields['filter'] as $f){
						foreach($f as $key => $val) $filters[$key] = $val;
					}

					$fields['filter'][$fields['source']] = $filters;
				}

				if(!isset($fields['xml_elements']) || !is_array($fields['xml_elements'])) {
					$fields['xml_elements'] = array();
				}
			}

			else if($this->_context[0] == 'edit'){
				$isEditing = true;
				$handle = $this->_context[1];
				$existing =& DatasourceManager::create($handle, array(), false);
				$cache_id = null;

				if (!$existing->allowEditorToParse()) redirect(SYMPHONY_URL . '/blueprints/datasources/info/' . $handle . '/');

				$about = $existing->about();
				$cache = new Cacheable(Symphony::Database());
				$fields['name'] = $about['name'];

				$fields['order'] = ($existing->dsParamORDER == 'rand' ? 'random' : $existing->dsParamORDER);
				$fields['param'] = $existing->dsParamPARAMOUTPUT;
				$fields['required_url_param'] = trim($existing->dsParamREQUIREDPARAM);

				if(isset($existing->dsParamINCLUDEDELEMENTS) && is_array($existing->dsParamINCLUDEDELEMENTS)){
					$fields['xml_elements'] = $existing->dsParamINCLUDEDELEMENTS;
				}
				else {
					$fields['xml_elements'] = array();
				}

				$fields['sort'] = $existing->dsParamSORT;
				$fields['paginate_results'] = isset($existing->dsParamPAGINATERESULTS) ? $existing->dsParamPAGINATERESULTS : 'yes';
				$fields['page_number'] = $existing->dsParamSTARTPAGE;
				$fields['group'] = isset($existing->dsParamGROUP) ? $existing->dsParamGROUP : null;
				$fields['html_encode'] = isset($existing->dsParamHTMLENCODE) ? $existing->dsParamHTMLENCODE : 'no';
				$fields['associated_entry_counts'] = $existing->dsParamASSOCIATEDENTRYCOUNTS;
				if(is_null($fields['associated_entry_counts'])) $fields['associated_entry_counts'] = 'yes';
				if($existing->dsParamREDIRECTONEMPTY == 'yes') $fields['redirect_on_empty'] = 'yes';

				if(!is_array($existing->dsParamFILTERS)) {
					$existing->dsParamFILTERS = array();
				}

				if(!empty($existing->dsParamFILTERS)) {
					$existing->dsParamFILTERS = array_map('stripslashes', $existing->dsParamFILTERS);
				}

				$fields['source'] = $existing->getSource();

				$provided = false;
				if(!empty($providers)) {
					foreach($providers as $providerClass => $provider) {
						if($fields['source'] == $providerClass::getClass()) {
							$fields = array_merge($fields, $existing->settings());
							$provided = true;
							break;
						}
					}
				}

				if($provided == false) {
					switch($fields['source']){
						case 'authors':
							$fields['filter']['author'] = $existing->dsParamFILTERS;
							break;

						case 'navigation':
							$fields['filter']['navigation'] = $existing->dsParamFILTERS;
							break;

						case 'dynamic_xml':
							$fields['dynamic_xml']['namespace'] = $existing->dsParamFILTERS;
							$fields['dynamic_xml']['url'] = $existing->dsParamURL;
							$fields['dynamic_xml']['xpath'] = $existing->dsParamXPATH;
							$fields['dynamic_xml']['cache'] = $existing->dsParamCACHE;
							$fields['dynamic_xml']['timeout'] = (isset($existing->dsParamTIMEOUT) ? $existing->dsParamTIMEOUT : 6);
							break;

						case 'static_xml':
							$existing->grab();
							if (!isset($existing->dsParamSTATIC))
								$fields['static_xml'] = trim($existing->dsSTATIC);
							else
								$fields['static_xml'] = trim($existing->dsParamSTATIC);
							break;
							break;

						default:
							$fields['filter'][$fields['source']] = $existing->dsParamFILTERS;
							$fields['max_records'] = $existing->dsParamLIMIT;
							break;
					}
				}
			}

			else{

				$fields['dynamic_xml']['url'] = '';
				$fields['dynamic_xml']['cache'] = '30';
				$fields['dynamic_xml']['xpath'] = '/';
				$fields['dynamic_xml']['timeout'] = '6';
				$fields['dynamic_xml']['format'] = 'XML';

				$fields['paginate_results'] = 'yes';
				$fields['max_records'] = '20';
				$fields['page_number'] = '1';

				$fields['order'] = 'desc';
				$fields['associated_entry_counts'] = NULL;

			}
			
			

			$this->setPageType('form');
			$this->setTitle(__(($isEditing ? '%1$s &ndash; %2$s &ndash; %3$s' : '%2$s &ndash; %3$s'), array($about['name'], __('Data Sources'), __('Symphony'))));
			$this->appendSubheading(($isEditing ? $about['name'] : __('Untitled')));
			$this->insertBreadcrumbs(array(
				Widget::Anchor(__('Data Sources'), SYMPHONY_URL . '/blueprints/datasources/'),
			));

			$fieldset = new XMLElement('fieldset');
			$fieldset->setAttribute('class', 'settings');
			$fieldset->appendChild(new XMLElement('legend', __('Essentials')));

			$group = new XMLElement('div');
			$group->setAttribute('class', 'two columns');

			$div = new XMLElement('div', NULL, array('class' => 'column'));
			$label = Widget::Label(__('Name'));
			$label->appendChild(Widget::Input('fields[name]', General::sanitize($fields['name'])));

			if(isset($this->_errors['name'])) $div->appendChild(Widget::Error($label, $this->_errors['name']));
			else $div->appendChild($label);
			$group->appendChild($div);

			$div = new XMLElement('div', NULL, array('class' => 'column'));
			$label = Widget::Label(__('Source'));

			$sections = SectionManager::fetch(NULL, 'ASC', 'name');

			if (!is_array($sections)) $sections = array();
			$field_groups = array();

			foreach($sections as $section){
				$field_groups[$section->get('id')] = array('fields' => $section->fetchFields(), 'section' => $section);
			}

			$options = array(
				array('label' => __('System'), 'options' => array(
						array('authors', ($fields['source'] == 'authors'), __('Authors')),
						array('navigation', ($fields['source'] == 'navigation'), __('Navigation')),
				)),
				array('label' => __('Custom XML'), 'options' => array(
						array('dynamic_xml', ($fields['source'] == 'dynamic_xml'), __('Dynamic XML')),
						array('static_xml', ($fields['source'] == 'static_xml'), __('Static XML')),
				)),
			);

			// Loop over the datasource providers
			if(!empty($providers)) {
				$p = array('label' => __('From extensions'), 'options' => array());

				foreach($providers as $providerClass => $provider) {
					$p['options'][] = array(
						$providerClass, ($fields['source'] == $providerClass), $provider
					);
				}

				$options[] = $p;
			}

			// Add Sections
			if(is_array($sections) && !empty($sections)){
				array_unshift($options, array('label' => __('Sections'), 'options' => array()));
				foreach($sections as $s) $options[0]['options'][] = array($s->get('id'), ($fields['source'] == $s->get('id')), General::sanitize($s->get('name')));
			}

			$label->appendChild(Widget::Select('fields[source]', $options, array('id' => 'ds-context')));
			$div->appendChild($label);
			$group->appendChild($div);

			$fieldset->appendChild($group);
			$this->Form->appendChild($fieldset);

			$fieldset = new XMLElement('fieldset');
			$fieldset->setAttribute('class', 'settings contextual authors navigation ' . __('Sections') . ' ' . __('System'));
			$fieldset->appendChild(new XMLElement('legend', __('Filter Results')));
			$p = new XMLElement('p',
				__('Use %s syntax to filter by page parameters.', array(
					'<code>{' . __('$param') . '}</code>'
				))
			);
			$p->setAttribute('class', 'help');
			$fieldset->appendChild($p);

			foreach($field_groups as $section_id => $section_data){
				$div = new XMLElement('div');
				$div->setAttribute('class', 'contextual ' . $section_data['section']->get('id'));

				$ol = new XMLElement('ol');
				$ol->setAttribute('class', 'filters-duplicator');
				$ol->setAttribute('data-add', __('Add filter'));
				$ol->setAttribute('data-remove', __('Remove filter'));

				// Add system:id filter
				if(isset($fields['filter'][$section_data['section']->get('id')]['id'])){
					$li = new XMLElement('li');
					$li->setAttribute('class', 'unique');
					$li->setAttribute('data-type', 'id');
					$li->appendChild(new XMLElement('header', '<h4>' . __('System ID') . '</h4>'));
					$label = Widget::Label(__('Value'));
					$label->appendChild(Widget::Input('fields[filter]['.$section_data['section']->get('id').'][id]', General::sanitize($fields['filter'][$section_data['section']->get('id')]['id'])));
					$li->appendChild($label);
					$ol->appendChild($li);
				}

				$li = new XMLElement('li');
				$li->setAttribute('class', 'unique template');
				$li->setAttribute('data-type', 'id');
				$li->appendChild(new XMLElement('header', '<h4>' . __('System ID') . '</h4>'));
				$label = Widget::Label(__('Value'));
				$label->appendChild(Widget::Input('fields[filter]['.$section_data['section']->get('id').'][id]'));
				$li->appendChild($label);
				$ol->appendChild($li);

				// Add system:date filter
				if(isset($fields['filter'][$section_data['section']->get('id')]['system:date'])){
					$li = new XMLElement('li');
					$li->setAttribute('class', 'unique');
					$li->setAttribute('data-type', 'system:date');
					$li->appendChild(new XMLElement('header', '<h4>' . __('System Date') . '</h4>'));
					$label = Widget::Label(__('Value'));
					$label->appendChild(Widget::Input('fields[filter]['.$section_data['section']->get('id').'][system:date]', General::sanitize($fields['filter'][$section_data['section']->get('id')]['system:date'])));
					$li->appendChild($label);
					$ol->appendChild($li);
				}

				$li = new XMLElement('li');
				$li->setAttribute('class', 'unique template');
				$li->setAttribute('data-type', 'system:date');
				$li->appendChild(new XMLElement('header', '<h4>' . __('System Date') . '</h4>'));
				$label = Widget::Label(__('Value'));
				$label->appendChild(Widget::Input('fields[filter]['.$section_data['section']->get('id').'][system:date]'));
				$li->appendChild($label);
				$ol->appendChild($li);

				if(is_array($section_data['fields']) && !empty($section_data['fields'])){
					foreach($section_data['fields'] as $input){

						if(!$input->canFilter()) continue;

						if(isset($fields['filter'][$section_data['section']->get('id')][$input->get('id')])){
							$wrapper = new XMLElement('li');
							$wrapper->setAttribute('class', 'unique');
							$wrapper->setAttribute('data-type', $input->get('element_name'));
							$input->displayDatasourceFilterPanel($wrapper, $fields['filter'][$section_data['section']->get('id')][$input->get('id')], $this->_errors[$input->get('id')], $section_data['section']->get('id'));
							$ol->appendChild($wrapper);
						}

						$wrapper = new XMLElement('li');
						$wrapper->setAttribute('class', 'unique template');
						$wrapper->setAttribute('data-type', $input->get('element_name'));
						$input->displayDatasourceFilterPanel($wrapper, NULL, NULL, $section_data['section']->get('id'));
						$ol->appendChild($wrapper);

					}
				}

				$div->appendChild($ol);

				$fieldset->appendChild($div);

			}

			$div = new XMLElement('div');
			$div->setAttribute('class', 'contextual authors');

			$ol = new XMLElement('ol');
			$ol->setAttribute('class', 'filters-duplicator');
			$ol->setAttribute('data-add', __('Add filter'));
			$ol->setAttribute('data-remove', __('Remove filter'));

			$this->__appendAuthorFilter($ol, __('ID'), 'id', $fields['filter']['author']['id'], (!isset($fields['filter']['author']['id'])));
			$this->__appendAuthorFilter($ol, __('Username'), 'username', $fields['filter']['author']['username'], (!isset($fields['filter']['author']['username'])));
			$this->__appendAuthorFilter($ol, __('First Name'), 'first_name', $fields['filter']['author']['first_name'], (!isset($fields['filter']['author']['first_name'])));
			$this->__appendAuthorFilter($ol, __('Last Name'), 'last_name', $fields['filter']['author']['last_name'], (!isset($fields['filter']['author']['last_name'])));
			$this->__appendAuthorFilter($ol, __('Email'), 'email', $fields['filter']['author']['email'], (!isset($fields['filter']['author']['email'])));
			$this->__appendAuthorFilter($ol, __('User Type'), 'user_type', $fields['filter']['author']['user_type'], (!isset($fields['filter']['author']['user_type'])));

			$div->appendChild($ol);

			$fieldset->appendChild($div);

			$div = new XMLElement('div');
			$div->setAttribute('class', 'contextual navigation');

			$ol = new XMLElement('ol');
			$ol->setAttribute('class', 'filters-duplicator');
			$ol->setAttribute('data-add', __('Add filter'));
			$ol->setAttribute('data-remove', __('Remove filter'));

			$ul = new XMLElement('ul');
			$ul->setAttribute('class', 'tags');

			$pages = PageManager::fetch(false, array('*'), array(), 'title ASC');

			foreach($pages as $page){
				$ul->appendChild(new XMLElement('li', preg_replace('/\/{2,}/i', '/', '/' . $page['path'] . '/' . $page['handle'])));
			}

			if(isset($fields['filter']['navigation']['parent'])){
				$li = new XMLElement('li');
				$li->setAttribute('class', 'unique');
				$li->setAttribute('data-type', 'parent');
				$li->appendChild(new XMLElement('header', '<h4>' . __('Parent Page') . '</h4>'));
				$label = Widget::Label(__('Value'));
				$label->appendChild(Widget::Input('fields[filter][navigation][parent]', General::sanitize($fields['filter']['navigation']['parent'])));
				$li->appendChild($label);
				$li->appendChild($ul);
				$ol->appendChild($li);
			}

			$li = new XMLElement('li');
			$li->setAttribute('class', 'unique template');
			$li->setAttribute('data-type', 'parent');
			$li->appendChild(new XMLElement('header', '<h4>' . __('Parent Page') . '</h4>'));
			$label = Widget::Label(__('Value'));
			$label->appendChild(Widget::Input('fields[filter][navigation][parent]'));
			$li->appendChild($label);
			$li->appendChild($ul);
			$ol->appendChild($li);

			$ul = new XMLElement('ul');
			$ul->setAttribute('class', 'tags');
			if($types = PageManager::fetchAvailablePageTypes()) {
				foreach($types as $type) {
					$ul->appendChild(new XMLElement('li', $type));
				}
			}

			if(isset($fields['filter']['navigation']['type'])){
				$li = new XMLElement('li');
				$li->setAttribute('class', 'unique');
				$li->setAttribute('data-type', 'type');
				$li->appendChild(new XMLElement('header', '<h4>' . __('Page Type') . '</h4>'));
				$label = Widget::Label(__('Value'));
				$label->appendChild(Widget::Input('fields[filter][navigation][type]', General::sanitize($fields['filter']['navigation']['type'])));
				$li->appendChild($label);
				$li->appendChild($ul);
				$ol->appendChild($li);
			}

			$li = new XMLElement('li');
			$li->setAttribute('class', 'unique template');
			$li->appendChild(new XMLElement('header', '<h4>' . __('Page Type') . '</h4>'));
			$li->setAttribute('data-type', 'type');
			$label = Widget::Label(__('Value'));
			$label->appendChild(Widget::Input('fields[filter][navigation][type]'));
			$li->appendChild($label);
			$li->appendChild($ul);
			$ol->appendChild($li);

			$div->appendChild($ol);

			$fieldset->appendChild($div);
			$this->Form->appendChild($fieldset);

			$fieldset = new XMLElement('fieldset');
			$fieldset->setAttribute('class', 'settings contextual inverse navigation authors static_xml dynamic_xml From_extensions');
			$fieldset->appendChild(new XMLElement('legend', __('Sorting and Limiting')));

			$p = new XMLElement('p',
				__('Use %s syntax to limit by page parameters.', array(
					'<code>{' . __('$param') . '}</code>'
				))
			);
			$p->setAttribute('class', 'help contextual inverse navigation');
			$fieldset->appendChild($p);

			$div = new XMLElement('div');
			$div->setAttribute('class', 'two columns contextual sections ' . __('Sections'));

			$label = Widget::Label(__('Sort By'), NULL, 'column');

			$options = array(
				array('label' => __('Authors'), 'options' => array(
						array('id', ($fields['source'] == 'authors' && $fields['sort'] == 'id'), __('Author ID')),
						array('username', ($fields['source'] == 'authors' && $fields['sort'] == 'username'), __('Username')),
						array('first-name', ($fields['source'] == 'authors' && $fields['sort'] == 'first-name'), __('First Name')),
						array('last-name', ($fields['source'] == 'authors' && $fields['sort'] == 'last-name'), __('Last Name')),
						array('email', ($fields['source'] == 'authors' && $fields['sort'] == 'email'), __('Email')),
						array('status', ($fields['source'] == 'authors' && $fields['sort'] == 'status'), __('Status')),
					)
				),

				array('label' => __('Navigation'), 'options' => array(
						array('id', ($fields['source'] == 'navigation' && $fields['sort'] == 'id'), __('Page ID')),
						array('handle', ($fields['source'] == 'navigation' && $fields['sort'] == 'handle'), __('Handle')),
						array('sortorder', ($fields['source'] == 'navigation' && $fields['sort'] == 'sortorder'), __('Sort Order')),
					)
				),
			);

			foreach($field_groups as $section_id => $section_data){
				$optgroup = array('label' => General::sanitize($section_data['section']->get('name')), 'options' => array(
					array('system:id', ($fields['source'] == $section_data['section']->get('id') && $fields['sort'] == 'system:id'), __('System ID')),
					array('system:date', ($fields['source'] == $section_data['section']->get('id') && $fields['sort'] == 'system:date'), __('System Date')),
				));

				if(is_array($section_data['fields']) && !empty($section_data['fields'])){
					foreach($section_data['fields'] as $input){

						if(!$input->isSortable()) continue;

						$optgroup['options'][] = array(
							$input->get('element_name'),
							($fields['source'] == $section_data['section']->get('id') && $input->get('element_name') == $fields['sort']),
							$input->get('label')
						);
					}
				}

				$options[] = $optgroup;
			}

			$label->appendChild(Widget::Select('fields[sort]', $options, array('class' => 'filtered')));
			$div->appendChild($label);

			$label = Widget::Label(__('Sort Order'), NULL, 'column');

			$options = array(
				array('asc', ('asc' == $fields['order']), __('ascending')),
				array('desc', ('desc' == $fields['order']), __('descending')),
				array('random', ('random' == $fields['order']), __('random')),
			);

			// Retain custom sort order
			if(!in_array($fields['order'], array('asc', 'desc', 'random'))){
				$options[] = array($fields['order'], true, $fields['order']);
			}

			$label->appendChild(Widget::Select('fields[order]', $options));
			$div->appendChild($label);

			$fieldset->appendChild($div);

			$label = Widget::Label();
			$input = array(
				Widget::Input('fields[paginate_results]', NULL, 'checkbox', ($fields['paginate_results'] == 'yes' ? array('checked' => 'checked') : NULL)),
				Widget::Input('fields[max_records]', $fields['max_records'], 'text', array('size' => '6')),
				Widget::Input('fields[page_number]', $fields['page_number'], 'text', array('size' => '6'))
			);
			$label->setValue(__('%1$s Paginate results, limiting to %2$s entries per page. Return page %3$s', array($input[0]->generate(false), $input[1]->generate(false), $input[2]->generate(false))));

			if(isset($this->_errors['max_records'])) $fieldset->appendChild(Widget::Error($label, $this->_errors['max_records']));
			else if(isset($this->_errors['page_number'])) $fieldset->appendChild(Widget::Error($label, $this->_errors['page_number']));
			else $fieldset->appendChild($label);

			$p = new XMLElement('p', __('Failing to paginate may degrade performance if the number of entries returned is very high.'), array('class' => 'help'));
			$fieldset->appendChild($p);

			$this->Form->appendChild($fieldset);

			$fieldset = new XMLElement('fieldset');
			$fieldset->setAttribute('class', 'settings contextual inverse navigation static_xml dynamic_xml From_extensions');
			$fieldset->appendChild(new XMLElement('legend', __('Output Options')));

			$label = Widget::Label(__('Required URL Parameter'));
			$label->appendChild(new XMLElement('i', __('Optional')));
			$label->appendChild(Widget::Input('fields[required_url_param]', trim($fields['required_url_param']), 'text', array('placeholder' => __('$param'))));
			$fieldset->appendChild($label);

			$p = new XMLElement('p', __('An empty result will be returned when this parameter does not have a value.'));
			$p->setAttribute('class', 'help');
			$fieldset->appendChild($p);

			$label = Widget::Label();
			$input = Widget::Input('fields[redirect_on_empty]', 'yes', 'checkbox', (isset($fields['redirect_on_empty']) ? array('checked' => 'checked') : NULL));
			$label->setValue(__('%s Redirect to 404 page when no results are found', array($input->generate(false))));
			$fieldset->appendChild($label);

			$div = new XMLElement('div', NULL, array('class' => 'two columns'));

			$subfieldset = new XMLElement('fieldset', NULL, array('class' => 'column'));
			$subfieldset->appendChild(new XMLElement('legend', __('Output Parameters')));

			// Support multiple parameters
			if(!is_array($fields['param'])) $fields['param'] = array($fields['param']);

			$label = Widget::Label(__('Use Fields'));
			$prefix = '$ds-' . (isset($this->_context[1]) ? Lang::createHandle($fields['name']) : '?') . '.';

			$options = array(
				array('label' => __('Authors'), 'options' => array())
			);

			foreach(array('id', 'username', 'name', 'email', 'user_type') as $p){
				$options[0]['options'][] = array(
					$p,
					($fields['source'] == 'authors' && in_array($p, $fields['param'])),
					$prefix . $p
				);
			}

			foreach($field_groups as $section_id => $section_data){
				$optgroup = array('label' => $section_data['section']->get('name'), 'options' => array());

				foreach(array('id', 'date', 'author') as $p){
					$optgroup['options'][] = array(
						'system:' . $p,
						($fields['source'] == $section_data['section']->get('id') && in_array('system:' . $p, $fields['param'])),
						$prefix . 'system-' . $p
					);
				}

				$authorOverride = false;

				if(is_array($section_data['fields']) && !empty($section_data['fields'])){
					foreach($section_data['fields'] as $input){

						if(!$input->allowDatasourceParamOutput()) continue;

						$optgroup['options'][] = array(
							$input->get('element_name'),
							($fields['source'] == $section_data['section']->get('id') && in_array($input->get('element_name'), $fields['param'])),
							$prefix . $input->get('element_name')
						);
					}
				}

				$options[] = $optgroup;
			}

			$label->appendChild(Widget::Select('fields[param][]', $options, array('class' => 'filtered', 'multiple' => 'multiple')));
			$subfieldset->appendChild($label);

			$div->appendChild($subfieldset);

			$subfieldset = new XMLElement('fieldset', NULL, array('class' => 'column'));
			$subfieldset->appendChild(new XMLElement('legend', __('XML Output')));

			$label = Widget::Label(__('Group By'));
			$options = array(
				array('', NULL, __('None')),
			);

			foreach($field_groups as $section_id => $section_data){
				$optgroup = array('label' => $section_data['section']->get('name'), 'options' => array());

				$authorOverride = false;

				if(is_array($section_data['fields']) && !empty($section_data['fields'])){
					foreach($section_data['fields'] as $input){

						if(!$input->allowDatasourceOutputGrouping()) continue;

						if($input->get('element_name') == 'author') $authorOverride = true;

						$optgroup['options'][] = array($input->get('id'), ($fields['source'] == $section_data['section']->get('id') && $fields['group'] == $input->get('id')), $input->get('label'));
					}
				}

				if(!$authorOverride) $optgroup['options'][] = array('author', ($fields['source'] == $section_data['section']->get('id') && $fields['group'] == 'author'), __('Author'));

				$options[] = $optgroup;
			}

			$label->appendChild(Widget::Select('fields[group]', $options, array('class' => 'filtered')));
			$subfieldset->appendChild($label);

			$label = Widget::Label(__('Included Elements'));

			$options = array(
				array('label' => __('Authors'), 'options' => array(
						array('username', ($fields['source'] == 'authors' && in_array('username', $fields['xml_elements'])), 'username'),
						array('name', ($fields['source'] == 'authors' && in_array('name', $fields['xml_elements'])), 'name'),
						array('email', ($fields['source'] == 'authors' && in_array('email', $fields['xml_elements'])), 'email'),
						array('author-token', ($fields['source'] == 'authors' && in_array('author-token', $fields['xml_elements'])), 'author-token'),
						array('default-area', ($fields['source'] == 'authors' && in_array('default-area', $fields['xml_elements'])), 'default-area'),
				)),
			);

			foreach($field_groups as $section_id => $section_data){
				$optgroup = array(
					'label' => General::sanitize($section_data['section']->get('name')),
					'options' => array(
						array(
							'system:pagination',
							($fields['source'] == $section_data['section']->get('id') && in_array('system:pagination', $fields['xml_elements'])),
							'system: pagination'
						)
					)
				);
				
				

				if(is_array($section_data['fields']) && !empty($section_data['fields'])){
					foreach($section_data['fields'] as $field){
						$elements = $field->fetchIncludableElements();
						
						if(is_array($elements) && !empty($elements)){
							foreach($elements as $name){
								$selected = false;

								if($fields['source'] == $section_data['section']->get('id') && in_array($name, $fields['xml_elements'])){
									$selected = true;
								}

								$optgroup['options'][] = array($name, $selected, $name);
							}
						}
					}
				}

				$options[] = $optgroup;
			}

			$label->appendChild(Widget::Select('fields[xml_elements][]', $options, array('multiple' => 'multiple', 'class' => 'filtered')));
			$subfieldset->appendChild($label);

			$label = Widget::Label();
			$label->setAttribute('class', 'contextual inverse authors');
			$input = Widget::Input('fields[associated_entry_counts]', 'yes', 'checkbox', ((isset($fields['associated_entry_counts']) && $fields['associated_entry_counts'] == 'yes') ? array('checked' => 'checked') : NULL));
			$label->setValue(__('%s Include a count of entries in associated sections', array($input->generate(false))));
			$subfieldset->appendChild($label);

			$label = Widget::Label();
			$label->setAttribute('class', 'contextual inverse authors');
			$input = Widget::Input('fields[html_encode]', 'yes', 'checkbox', (isset($fields['html_encode']) ? array('checked' => 'checked') : NULL));
			$label->setValue(__('%s HTML-encode text', array($input->generate(false))));
			$subfieldset->appendChild($label);

			$div->appendChild($subfieldset);

			$fieldset->appendChild($div);
			$this->Form->appendChild($fieldset);

		// Dynamic XML

			$fieldset = new XMLElement('fieldset');
			$fieldset->setAttribute('class', 'settings contextual dynamic_xml');
			$fieldset->appendChild(new XMLElement('legend', __('Dynamic XML')));

			$label = Widget::Label(__('URL'));
			$label->appendChild(Widget::Input('fields[dynamic_xml][url]', General::sanitize($fields['dynamic_xml']['url'])));
			if(isset($this->_errors['dynamic_xml']['url'])) $fieldset->appendChild(Widget::Error($label, $this->_errors['dynamic_xml']['url']));
			else $fieldset->appendChild($label);

			$p = new XMLElement('p',
				__('Use %s syntax to specify dynamic portions of the URL.', array(
					'<code>{' . __('$param') . '}</code>'
				))
			);
			$p->setAttribute('class', 'help');
			$label->appendChild($p);

			$div = new XMLElement('div');
			$p = new XMLElement('p', __('Namespace Declarations'));<commit_msg>Only check the HTML Encode option on the DSE when a user has actually checked it. Fixes #1178<commit_after><?php

	/**
	 * @package content
	 */
	/**
	 * The Datasource Editor page allows a developer to create new datasources
	 * from the four Symphony types, Section, Authors, Navigation, Dynamic XML,
	 * and Static XML
	 */
	require_once(TOOLKIT . '/class.gateway.php');
	require_once(TOOLKIT . '/class.resourcespage.php');

	Class contentBlueprintsDatasources extends ResourcesPage{

		public $_errors = array();

		public function __viewIndex($resource_type){
			parent::__viewIndex(RESOURCE_TYPE_DS);

			$this->setTitle(__('%1$s &ndash; %2$s', array(__('Data Sources'), __('Symphony'))));
			$this->appendSubheading(__('Data Sources'), Widget::Anchor(__('Create New'), Administration::instance()->getCurrentPageURL().'new/', __('Create a new data source'), 'create button', NULL, array('accesskey' => 'c')));
		}

		// Both the Edit and New pages need the same form
		public function __viewNew(){
			$this->__form();
		}

		public function __viewEdit(){
			$this->__form();
		}

		public function __form(){
			$formHasErrors = (is_array($this->_errors) && !empty($this->_errors));
			if($formHasErrors) {
				$this->pageAlert(
					__('An error occurred while processing this form. See below for details.')
					, Alert::ERROR
				);
			}
			// These alerts are only valid if the form doesn't have errors
			else if(isset($this->_context[2])) {
				switch($this->_context[2]) {
					case 'saved':
						$this->pageAlert(
							__('Data source updated at %s.', array(DateTimeObj::getTimeAgo()))
							. ' <a href="' . SYMPHONY_URL . '/blueprints/datasources/new/" accesskey="c">'
							. __('Create another?')
							. '</a> <a href="' . SYMPHONY_URL . '/blueprints/datasources/" accesskey="a">'
							. __('View all Data sources')
							. '</a>'
							, Alert::SUCCESS);
						break;

					case 'created':
						$this->pageAlert(
							__('Data source created at %s.', array(DateTimeObj::getTimeAgo()))
							. ' <a href="' . SYMPHONY_URL . '/blueprints/datasources/new/" accesskey="c">'
							. __('Create another?')
							. '</a> <a href="' . SYMPHONY_URL . '/blueprints/datasources/" accesskey="a">'
							. __('View all Data sources')
							. '</a>'
							, Alert::SUCCESS);
						break;
				}
			}

			$providers = Symphony::ExtensionManager()->getProvidersOf('data-sources');

			if(isset($_POST['fields'])){
				$fields = $_POST['fields'];
				$fields['paginate_results'] = ($fields['paginate_results'] == 'on') ? 'yes' : 'no';

				if(!in_array($fields['source'], array('authors', 'navigation', 'dynamic_xml', 'static_xml')) && is_array($fields['filter']) && !empty($fields['filter'])){
					$filters = array();
					foreach($fields['filter'] as $f){
						foreach($f as $key => $val) $filters[$key] = $val;
					}

					$fields['filter'][$fields['source']] = $filters;
				}

				if(!isset($fields['xml_elements']) || !is_array($fields['xml_elements'])) {
					$fields['xml_elements'] = array();
				}
			}

			else if($this->_context[0] == 'edit'){
				$isEditing = true;
				$handle = $this->_context[1];
				$existing =& DatasourceManager::create($handle, array(), false);
				$cache_id = null;

				if (!$existing->allowEditorToParse()) redirect(SYMPHONY_URL . '/blueprints/datasources/info/' . $handle . '/');

				$about = $existing->about();
				$cache = new Cacheable(Symphony::Database());
				$fields['name'] = $about['name'];

				$fields['order'] = ($existing->dsParamORDER == 'rand' ? 'random' : $existing->dsParamORDER);
				$fields['param'] = $existing->dsParamPARAMOUTPUT;
				$fields['required_url_param'] = trim($existing->dsParamREQUIREDPARAM);

				if(isset($existing->dsParamINCLUDEDELEMENTS) && is_array($existing->dsParamINCLUDEDELEMENTS)){
					$fields['xml_elements'] = $existing->dsParamINCLUDEDELEMENTS;
				}
				else {
					$fields['xml_elements'] = array();
				}

				$fields['sort'] = $existing->dsParamSORT;
				$fields['paginate_results'] = isset($existing->dsParamPAGINATERESULTS) ? $existing->dsParamPAGINATERESULTS : 'yes';
				$fields['page_number'] = $existing->dsParamSTARTPAGE;
				$fields['group'] = isset($existing->dsParamGROUP) ? $existing->dsParamGROUP : null;
				$fields['html_encode'] = isset($existing->dsParamHTMLENCODE) ? $existing->dsParamHTMLENCODE : 'no';
				$fields['associated_entry_counts'] = $existing->dsParamASSOCIATEDENTRYCOUNTS;
				if(is_null($fields['associated_entry_counts'])) $fields['associated_entry_counts'] = 'yes';
				if($existing->dsParamREDIRECTONEMPTY == 'yes') $fields['redirect_on_empty'] = 'yes';

				if(!is_array($existing->dsParamFILTERS)) {
					$existing->dsParamFILTERS = array();
				}

				if(!empty($existing->dsParamFILTERS)) {
					$existing->dsParamFILTERS = array_map('stripslashes', $existing->dsParamFILTERS);
				}

				$fields['source'] = $existing->getSource();

				$provided = false;
				if(!empty($providers)) {
					foreach($providers as $providerClass => $provider) {
						if($fields['source'] == $providerClass::getClass()) {
							$fields = array_merge($fields, $existing->settings());
							$provided = true;
							break;
						}
					}
				}

				if($provided == false) {
					switch($fields['source']){
						case 'authors':
							$fields['filter']['author'] = $existing->dsParamFILTERS;
							break;

						case 'navigation':
							$fields['filter']['navigation'] = $existing->dsParamFILTERS;
							break;

						case 'dynamic_xml':
							$fields['dynamic_xml']['namespace'] = $existing->dsParamFILTERS;
							$fields['dynamic_xml']['url'] = $existing->dsParamURL;
							$fields['dynamic_xml']['xpath'] = $existing->dsParamXPATH;
							$fields['dynamic_xml']['cache'] = $existing->dsParamCACHE;
							$fields['dynamic_xml']['timeout'] = (isset($existing->dsParamTIMEOUT) ? $existing->dsParamTIMEOUT : 6);
							break;

						case 'static_xml':
							$existing->grab();
							if (!isset($existing->dsParamSTATIC))
								$fields['static_xml'] = trim($existing->dsSTATIC);
							else
								$fields['static_xml'] = trim($existing->dsParamSTATIC);
							break;
							break;

						default:
							$fields['filter'][$fields['source']] = $existing->dsParamFILTERS;
							$fields['max_records'] = $existing->dsParamLIMIT;
							break;
					}
				}
			}

			else{

				$fields['dynamic_xml']['url'] = '';
				$fields['dynamic_xml']['cache'] = '30';
				$fields['dynamic_xml']['xpath'] = '/';
				$fields['dynamic_xml']['timeout'] = '6';
				$fields['dynamic_xml']['format'] = 'XML';

				$fields['paginate_results'] = 'yes';
				$fields['max_records'] = '20';
				$fields['page_number'] = '1';

				$fields['order'] = 'desc';
				$fields['associated_entry_counts'] = NULL;

			}
			
			

			$this->setPageType('form');
			$this->setTitle(__(($isEditing ? '%1$s &ndash; %2$s &ndash; %3$s' : '%2$s &ndash; %3$s'), array($about['name'], __('Data Sources'), __('Symphony'))));
			$this->appendSubheading(($isEditing ? $about['name'] : __('Untitled')));
			$this->insertBreadcrumbs(array(
				Widget::Anchor(__('Data Sources'), SYMPHONY_URL . '/blueprints/datasources/'),
			));

			$fieldset = new XMLElement('fieldset');
			$fieldset->setAttribute('class', 'settings');
			$fieldset->appendChild(new XMLElement('legend', __('Essentials')));

			$group = new XMLElement('div');
			$group->setAttribute('class', 'two columns');

			$div = new XMLElement('div', NULL, array('class' => 'column'));
			$label = Widget::Label(__('Name'));
			$label->appendChild(Widget::Input('fields[name]', General::sanitize($fields['name'])));

			if(isset($this->_errors['name'])) $div->appendChild(Widget::Error($label, $this->_errors['name']));
			else $div->appendChild($label);
			$group->appendChild($div);

			$div = new XMLElement('div', NULL, array('class' => 'column'));
			$label = Widget::Label(__('Source'));

			$sections = SectionManager::fetch(NULL, 'ASC', 'name');

			if (!is_array($sections)) $sections = array();
			$field_groups = array();

			foreach($sections as $section){
				$field_groups[$section->get('id')] = array('fields' => $section->fetchFields(), 'section' => $section);
			}

			$options = array(
				array('label' => __('System'), 'options' => array(
						array('authors', ($fields['source'] == 'authors'), __('Authors')),
						array('navigation', ($fields['source'] == 'navigation'), __('Navigation')),
				)),
				array('label' => __('Custom XML'), 'options' => array(
						array('dynamic_xml', ($fields['source'] == 'dynamic_xml'), __('Dynamic XML')),
						array('static_xml', ($fields['source'] == 'static_xml'), __('Static XML')),
				)),
			);

			// Loop over the datasource providers
			if(!empty($providers)) {
				$p = array('label' => __('From extensions'), 'options' => array());

				foreach($providers as $providerClass => $provider) {
					$p['options'][] = array(
						$providerClass, ($fields['source'] == $providerClass), $provider
					);
				}

				$options[] = $p;
			}

			// Add Sections
			if(is_array($sections) && !empty($sections)){
				array_unshift($options, array('label' => __('Sections'), 'options' => array()));
				foreach($sections as $s) $options[0]['options'][] = array($s->get('id'), ($fields['source'] == $s->get('id')), General::sanitize($s->get('name')));
			}

			$label->appendChild(Widget::Select('fields[source]', $options, array('id' => 'ds-context')));
			$div->appendChild($label);
			$group->appendChild($div);

			$fieldset->appendChild($group);
			$this->Form->appendChild($fieldset);

			$fieldset = new XMLElement('fieldset');
			$fieldset->setAttribute('class', 'settings contextual authors navigation ' . __('Sections') . ' ' . __('System'));
			$fieldset->appendChild(new XMLElement('legend', __('Filter Results')));
			$p = new XMLElement('p',
				__('Use %s syntax to filter by page parameters.', array(
					'<code>{' . __('$param') . '}</code>'
				))
			);
			$p->setAttribute('class', 'help');
			$fieldset->appendChild($p);

			foreach($field_groups as $section_id => $section_data){
				$div = new XMLElement('div');
				$div->setAttribute('class', 'contextual ' . $section_data['section']->get('id'));

				$ol = new XMLElement('ol');
				$ol->setAttribute('class', 'filters-duplicator');
				$ol->setAttribute('data-add', __('Add filter'));
				$ol->setAttribute('data-remove', __('Remove filter'));

				// Add system:id filter
				if(isset($fields['filter'][$section_data['section']->get('id')]['id'])){
					$li = new XMLElement('li');
					$li->setAttribute('class', 'unique');
					$li->setAttribute('data-type', 'id');
					$li->appendChild(new XMLElement('header', '<h4>' . __('System ID') . '</h4>'));
					$label = Widget::Label(__('Value'));
					$label->appendChild(Widget::Input('fields[filter]['.$section_data['section']->get('id').'][id]', General::sanitize($fields['filter'][$section_data['section']->get('id')]['id'])));
					$li->appendChild($label);
					$ol->appendChild($li);
				}

				$li = new XMLElement('li');
				$li->setAttribute('class', 'unique template');
				$li->setAttribute('data-type', 'id');
				$li->appendChild(new XMLElement('header', '<h4>' . __('System ID') . '</h4>'));
				$label = Widget::Label(__('Value'));
				$label->appendChild(Widget::Input('fields[filter]['.$section_data['section']->get('id').'][id]'));
				$li->appendChild($label);
				$ol->appendChild($li);

				// Add system:date filter
				if(isset($fields['filter'][$section_data['section']->get('id')]['system:date'])){
					$li = new XMLElement('li');
					$li->setAttribute('class', 'unique');
					$li->setAttribute('data-type', 'system:date');
					$li->appendChild(new XMLElement('header', '<h4>' . __('System Date') . '</h4>'));
					$label = Widget::Label(__('Value'));
					$label->appendChild(Widget::Input('fields[filter]['.$section_data['section']->get('id').'][system:date]', General::sanitize($fields['filter'][$section_data['section']->get('id')]['system:date'])));
					$li->appendChild($label);
					$ol->appendChild($li);
				}

				$li = new XMLElement('li');
				$li->setAttribute('class', 'unique template');
				$li->setAttribute('data-type', 'system:date');
				$li->appendChild(new XMLElement('header', '<h4>' . __('System Date') . '</h4>'));
				$label = Widget::Label(__('Value'));
				$label->appendChild(Widget::Input('fields[filter]['.$section_data['section']->get('id').'][system:date]'));
				$li->appendChild($label);
				$ol->appendChild($li);

				if(is_array($section_data['fields']) && !empty($section_data['fields'])){
					foreach($section_data['fields'] as $input){

						if(!$input->canFilter()) continue;

						if(isset($fields['filter'][$section_data['section']->get('id')][$input->get('id')])){
							$wrapper = new XMLElement('li');
							$wrapper->setAttribute('class', 'unique');
							$wrapper->setAttribute('data-type', $input->get('element_name'));
							$input->displayDatasourceFilterPanel($wrapper, $fields['filter'][$section_data['section']->get('id')][$input->get('id')], $this->_errors[$input->get('id')], $section_data['section']->get('id'));
							$ol->appendChild($wrapper);
						}

						$wrapper = new XMLElement('li');
						$wrapper->setAttribute('class', 'unique template');
						$wrapper->setAttribute('data-type', $input->get('element_name'));
						$input->displayDatasourceFilterPanel($wrapper, NULL, NULL, $section_data['section']->get('id'));
						$ol->appendChild($wrapper);

					}
				}

				$div->appendChild($ol);

				$fieldset->appendChild($div);

			}

			$div = new XMLElement('div');
			$div->setAttribute('class', 'contextual authors');

			$ol = new XMLElement('ol');
			$ol->setAttribute('class', 'filters-duplicator');
			$ol->setAttribute('data-add', __('Add filter'));
			$ol->setAttribute('data-remove', __('Remove filter'));

			$this->__appendAuthorFilter($ol, __('ID'), 'id', $fields['filter']['author']['id'], (!isset($fields['filter']['author']['id'])));
			$this->__appendAuthorFilter($ol, __('Username'), 'username', $fields['filter']['author']['username'], (!isset($fields['filter']['author']['username'])));
			$this->__appendAuthorFilter($ol, __('First Name'), 'first_name', $fields['filter']['author']['first_name'], (!isset($fields['filter']['author']['first_name'])));
			$this->__appendAuthorFilter($ol, __('Last Name'), 'last_name', $fields['filter']['author']['last_name'], (!isset($fields['filter']['author']['last_name'])));
			$this->__appendAuthorFilter($ol, __('Email'), 'email', $fields['filter']['author']['email'], (!isset($fields['filter']['author']['email'])));
			$this->__appendAuthorFilter($ol, __('User Type'), 'user_type', $fields['filter']['author']['user_type'], (!isset($fields['filter']['author']['user_type'])));

			$div->appendChild($ol);

			$fieldset->appendChild($div);

			$div = new XMLElement('div');
			$div->setAttribute('class', 'contextual navigation');

			$ol = new XMLElement('ol');
			$ol->setAttribute('class', 'filters-duplicator');
			$ol->setAttribute('data-add', __('Add filter'));
			$ol->setAttribute('data-remove', __('Remove filter'));

			$ul = new XMLElement('ul');
			$ul->setAttribute('class', 'tags');

			$pages = PageManager::fetch(false, array('*'), array(), 'title ASC');

			foreach($pages as $page){
				$ul->appendChild(new XMLElement('li', preg_replace('/\/{2,}/i', '/', '/' . $page['path'] . '/' . $page['handle'])));
			}

			if(isset($fields['filter']['navigation']['parent'])){
				$li = new XMLElement('li');
				$li->setAttribute('class', 'unique');
				$li->setAttribute('data-type', 'parent');
				$li->appendChild(new XMLElement('header', '<h4>' . __('Parent Page') . '</h4>'));
				$label = Widget::Label(__('Value'));
				$label->appendChild(Widget::Input('fields[filter][navigation][parent]', General::sanitize($fields['filter']['navigation']['parent'])));
				$li->appendChild($label);
				$li->appendChild($ul);
				$ol->appendChild($li);
			}

			$li = new XMLElement('li');
			$li->setAttribute('class', 'unique template');
			$li->setAttribute('data-type', 'parent');
			$li->appendChild(new XMLElement('header', '<h4>' . __('Parent Page') . '</h4>'));
			$label = Widget::Label(__('Value'));
			$label->appendChild(Widget::Input('fields[filter][navigation][parent]'));
			$li->appendChild($label);
			$li->appendChild($ul);
			$ol->appendChild($li);

			$ul = new XMLElement('ul');
			$ul->setAttribute('class', 'tags');
			if($types = PageManager::fetchAvailablePageTypes()) {
				foreach($types as $type) {
					$ul->appendChild(new XMLElement('li', $type));
				}
			}

			if(isset($fields['filter']['navigation']['type'])){
				$li = new XMLElement('li');
				$li->setAttribute('class', 'unique');
				$li->setAttribute('data-type', 'type');
				$li->appendChild(new XMLElement('header', '<h4>' . __('Page Type') . '</h4>'));
				$label = Widget::Label(__('Value'));
				$label->appendChild(Widget::Input('fields[filter][navigation][type]', General::sanitize($fields['filter']['navigation']['type'])));
				$li->appendChild($label);
				$li->appendChild($ul);
				$ol->appendChild($li);
			}

			$li = new XMLElement('li');
			$li->setAttribute('class', 'unique template');
			$li->appendChild(new XMLElement('header', '<h4>' . __('Page Type') . '</h4>'));
			$li->setAttribute('data-type', 'type');
			$label = Widget::Label(__('Value'));
			$label->appendChild(Widget::Input('fields[filter][navigation][type]'));
			$li->appendChild($label);
			$li->appendChild($ul);
			$ol->appendChild($li);

			$div->appendChild($ol);

			$fieldset->appendChild($div);
			$this->Form->appendChild($fieldset);

			$fieldset = new XMLElement('fieldset');
			$fieldset->setAttribute('class', 'settings contextual inverse navigation authors static_xml dynamic_xml From_extensions');
			$fieldset->appendChild(new XMLElement('legend', __('Sorting and Limiting')));

			$p = new XMLElement('p',
				__('Use %s syntax to limit by page parameters.', array(
					'<code>{' . __('$param') . '}</code>'
				))
			);
			$p->setAttribute('class', 'help contextual inverse navigation');
			$fieldset->appendChild($p);

			$div = new XMLElement('div');
			$div->setAttribute('class', 'two columns contextual sections ' . __('Sections'));

			$label = Widget::Label(__('Sort By'), NULL, 'column');

			$options = array(
				array('label' => __('Authors'), 'options' => array(
						array('id', ($fields['source'] == 'authors' && $fields['sort'] == 'id'), __('Author ID')),
						array('username', ($fields['source'] == 'authors' && $fields['sort'] == 'username'), __('Username')),
						array('first-name', ($fields['source'] == 'authors' && $fields['sort'] == 'first-name'), __('First Name')),
						array('last-name', ($fields['source'] == 'authors' && $fields['sort'] == 'last-name'), __('Last Name')),
						array('email', ($fields['source'] == 'authors' && $fields['sort'] == 'email'), __('Email')),
						array('status', ($fields['source'] == 'authors' && $fields['sort'] == 'status'), __('Status')),
					)
				),

				array('label' => __('Navigation'), 'options' => array(
						array('id', ($fields['source'] == 'navigation' && $fields['sort'] == 'id'), __('Page ID')),
						array('handle', ($fields['source'] == 'navigation' && $fields['sort'] == 'handle'), __('Handle')),
						array('sortorder', ($fields['source'] == 'navigation' && $fields['sort'] == 'sortorder'), __('Sort Order')),
					)
				),
			);

			foreach($field_groups as $section_id => $section_data){
				$optgroup = array('label' => General::sanitize($section_data['section']->get('name')), 'options' => array(
					array('system:id', ($fields['source'] == $section_data['section']->get('id') && $fields['sort'] == 'system:id'), __('System ID')),
					array('system:date', ($fields['source'] == $section_data['section']->get('id') && $fields['sort'] == 'system:date'), __('System Date')),
				));

				if(is_array($section_data['fields']) && !empty($section_data['fields'])){
					foreach($section_data['fields'] as $input){

						if(!$input->isSortable()) continue;

						$optgroup['options'][] = array(
							$input->get('element_name'),
							($fields['source'] == $section_data['section']->get('id') && $input->get('element_name') == $fields['sort']),
							$input->get('label')
						);
					}
				}

				$options[] = $optgroup;
			}

			$label->appendChild(Widget::Select('fields[sort]', $options, array('class' => 'filtered')));
			$div->appendChild($label);

			$label = Widget::Label(__('Sort Order'), NULL, 'column');

			$options = array(
				array('asc', ('asc' == $fields['order']), __('ascending')),
				array('desc', ('desc' == $fields['order']), __('descending')),
				array('random', ('random' == $fields['order']), __('random')),
			);

			// Retain custom sort order
			if(!in_array($fields['order'], array('asc', 'desc', 'random'))){
				$options[] = array($fields['order'], true, $fields['order']);
			}

			$label->appendChild(Widget::Select('fields[order]', $options));
			$div->appendChild($label);

			$fieldset->appendChild($div);

			$label = Widget::Label();
			$input = array(
				Widget::Input('fields[paginate_results]', NULL, 'checkbox', ($fields['paginate_results'] == 'yes' ? array('checked' => 'checked') : NULL)),
				Widget::Input('fields[max_records]', $fields['max_records'], 'text', array('size' => '6')),
				Widget::Input('fields[page_number]', $fields['page_number'], 'text', array('size' => '6'))
			);
			$label->setValue(__('%1$s Paginate results, limiting to %2$s entries per page. Return page %3$s', array($input[0]->generate(false), $input[1]->generate(false), $input[2]->generate(false))));

			if(isset($this->_errors['max_records'])) $fieldset->appendChild(Widget::Error($label, $this->_errors['max_records']));
			else if(isset($this->_errors['page_number'])) $fieldset->appendChild(Widget::Error($label, $this->_errors['page_number']));
			else $fieldset->appendChild($label);

			$p = new XMLElement('p', __('Failing to paginate may degrade performance if the number of entries returned is very high.'), array('class' => 'help'));
			$fieldset->appendChild($p);

			$this->Form->appendChild($fieldset);

			$fieldset = new XMLElement('fieldset');
			$fieldset->setAttribute('class', 'settings contextual inverse navigation static_xml dynamic_xml From_extensions');
			$fieldset->appendChild(new XMLElement('legend', __('Output Options')));

			$label = Widget::Label(__('Required URL Parameter'));
			$label->appendChild(new XMLElement('i', __('Optional')));
			$label->appendChild(Widget::Input('fields[required_url_param]', trim($fields['required_url_param']), 'text', array('placeholder' => __('$param'))));
			$fieldset->appendChild($label);

			$p = new XMLElement('p', __('An empty result will be returned when this parameter does not have a value.'));
			$p->setAttribute('class', 'help');
			$fieldset->appendChild($p);

			$label = Widget::Label();
			$input = Widget::Input('fields[redirect_on_empty]', 'yes', 'checkbox', (isset($fields['redirect_on_empty']) ? array('checked' => 'checked') : NULL));
			$label->setValue(__('%s Redirect to 404 page when no results are found', array($input->generate(false))));
			$fieldset->appendChild($label);

			$div = new XMLElement('div', NULL, array('class' => 'two columns'));

			$subfieldset = new XMLElement('fieldset', NULL, array('class' => 'column'));
			$subfieldset->appendChild(new XMLElement('legend', __('Output Parameters')));

			// Support multiple parameters
			if(!is_array($fields['param'])) $fields['param'] = array($fields['param']);

			$label = Widget::Label(__('Use Fields'));
			$prefix = '$ds-' . (isset($this->_context[1]) ? Lang::createHandle($fields['name']) : '?') . '.';

			$options = array(
				array('label' => __('Authors'), 'options' => array())
			);

			foreach(array('id', 'username', 'name', 'email', 'user_type') as $p){
				$options[0]['options'][] = array(
					$p,
					($fields['source'] == 'authors' && in_array($p, $fields['param'])),
					$prefix . $p
				);
			}

			foreach($field_groups as $section_id => $section_data){
				$optgroup = array('label' => $section_data['section']->get('name'), 'options' => array());

				foreach(array('id', 'date', 'author') as $p){
					$optgroup['options'][] = array(
						'system:' . $p,
						($fields['source'] == $section_data['section']->get('id') && in_array('system:' . $p, $fields['param'])),
						$prefix . 'system-' . $p
					);
				}

				$authorOverride = false;

				if(is_array($section_data['fields']) && !empty($section_data['fields'])){
					foreach($section_data['fields'] as $input){

						if(!$input->allowDatasourceParamOutput()) continue;

						$optgroup['options'][] = array(
							$input->get('element_name'),
							($fields['source'] == $section_data['section']->get('id') && in_array($input->get('element_name'), $fields['param'])),
							$prefix . $input->get('element_name')
						);
					}
				}

				$options[] = $optgroup;
			}

			$label->appendChild(Widget::Select('fields[param][]', $options, array('class' => 'filtered', 'multiple' => 'multiple')));
			$subfieldset->appendChild($label);

			$div->appendChild($subfieldset);

			$subfieldset = new XMLElement('fieldset', NULL, array('class' => 'column'));
			$subfieldset->appendChild(new XMLElement('legend', __('XML Output')));

			$label = Widget::Label(__('Group By'));
			$options = array(
				array('', NULL, __('None')),
			);

			foreach($field_groups as $section_id => $section_data){
				$optgroup = array('label' => $section_data['section']->get('name'), 'options' => array());

				$authorOverride = false;

				if(is_array($section_data['fields']) && !empty($section_data['fields'])){
					foreach($section_data['fields'] as $input){

						if(!$input->allowDatasourceOutputGrouping()) continue;

						if($input->get('element_name') == 'author') $authorOverride = true;

						$optgroup['options'][] = array($input->get('id'), ($fields['source'] == $section_data['section']->get('id') && $fields['group'] == $input->get('id')), $input->get('label'));
					}
				}

				if(!$authorOverride) $optgroup['options'][] = array('author', ($fields['source'] == $section_data['section']->get('id') && $fields['group'] == 'author'), __('Author'));

				$options[] = $optgroup;
			}

			$label->appendChild(Widget::Select('fields[group]', $options, array('class' => 'filtered')));
			$subfieldset->appendChild($label);

			$label = Widget::Label(__('Included Elements'));

			$options = array(
				array('label' => __('Authors'), 'options' => array(
						array('username', ($fields['source'] == 'authors' && in_array('username', $fields['xml_elements'])), 'username'),
						array('name', ($fields['source'] == 'authors' && in_array('name', $fields['xml_elements'])), 'name'),
						array('email', ($fields['source'] == 'authors' && in_array('email', $fields['xml_elements'])), 'email'),
						array('author-token', ($fields['source'] == 'authors' && in_array('author-token', $fields['xml_elements'])), 'author-token'),
						array('default-area', ($fields['source'] == 'authors' && in_array('default-area', $fields['xml_elements'])), 'default-area'),
				)),
			);

			foreach($field_groups as $section_id => $section_data){
				$optgroup = array(
					'label' => General::sanitize($section_data['section']->get('name')),
					'options' => array(
						array(
							'system:pagination',
							($fields['source'] == $section_data['section']->get('id') && in_array('system:pagination', $fields['xml_elements'])),
							'system: pagination'
						)
					)
				);
				
				

				if(is_array($section_data['fields']) && !empty($section_data['fields'])){
					foreach($section_data['fields'] as $field){
						$elements = $field->fetchIncludableElements();
						
						if(is_array($elements) && !empty($elements)){
							foreach($elements as $name){
								$selected = false;

								if($fields['source'] == $section_data['section']->get('id') && in_array($name, $fields['xml_elements'])){
									$selected = true;
								}

								$optgroup['options'][] = array($name, $selected, $name);
							}
						}
					}
				}

				$options[] = $optgroup;
			}

			$label->appendChild(Widget::Select('fields[xml_elements][]', $options, array('multiple' => 'multiple', 'class' => 'filtered')));
			$subfieldset->appendChild($label);

			$label = Widget::Label();
			$label->setAttribute('class', 'contextual inverse authors');
			$input = Widget::Input('fields[associated_entry_counts]', 'yes', 'checkbox', ((isset($fields['associated_entry_counts']) && $fields['associated_entry_counts'] == 'yes') ? array('checked' => 'checked') : NULL));
			$label->setValue(__('%s Include a count of entries in associated sections', array($input->generate(false))));
			$subfieldset->appendChild($label);

			$label = Widget::Label();
			$label->setAttribute('class', 'contextual inverse authors');
			$input = Widget::Input('fields[html_encode]', 'yes', 'checkbox', (isset($fields['html_encode']) && $fields['html_encode'] == 'yes' ? array('checked' => 'checked') : NULL));
			$label->setValue(__('%s HTML-encode text', array($input->generate(false))));
			$subfieldset->appendChild($label);

			$div->appendChild($subfieldset);

			$fieldset->appendChild($div);
			$this->Form->appendChild($fieldset);

		// Dynamic XML

			$fieldset = new XMLElement('fieldset');
			$fieldset->setAttribute('class', 'settings contextual dynamic_xml');
			$fieldset->appendChild(new XMLElement('legend', __('Dynamic XML')));

			$label = Widget::Label(__('URL'));
			$label->appendChild(Widget::Input('fields[dynamic_xml][url]', General::sanitize($fields['dynamic_xml']['url'])));
			if(isset($this->_errors['dynamic_xml']['url'])) $fieldset->appendChild(Widget::Error($label, $this->_errors['dynamic_xml']['url']));
			else $fieldset->appendChild($label);

			$p = new XMLElement('p',
				__('Use %s syntax to specify dynamic portions of the URL.', array(
					'<code>{' . __('$param') . '}</code>'
				))
			);
			$p->setAttribute('class', 'help');
			$label->appendChild($p);

			$div = new XMLElement('div');
			$p = new XMLElement('p', __('Namespace Declarations'));
{'fraction_non_alphanumeric': 0.23530491365646117, 'fraction_numerical': 0.0017018436639693, 'mean_word_length': 4.783653382225224, 'pattern_counts': {'":': 0, '<': 65, '<?xml version=': 0, '>': 743, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 84}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6196516', 'n_tokens_mistral': 22540, 'n_tokens_neox': 18659, 'n_words': 3162}