<commit_before><?php

/**
 * @package userforms
 */

class UserDefinedForm extends Page {

	/**
	 * @var string
	 */
	private static $description = 'Adds a customizable form.';

	/**
	 * @var string Required Identifier
	 */
	private static $required_identifier = null;

	/**
	 * @var string
	 */
	private static $email_template_directory = 'userforms/templates/email/';

	/**
	 * Should this module automatically upgrade on dev/build?
	 *
	 * @config
	 * @var bool
	 */
	private static $upgrade_on_build = true;

	/**
	 * Built in extensions required by this page
	 * @config
	 * @var array
	 */
	private static $extensions = array(
		'UserFormFieldEditorExtension'
	);

	/**
	 * @var array Fields on the user defined form page.
	 */
	private static $db = array(
		"SubmitButtonText" => "Varchar",
		"ClearButtonText" => "Varchar",
		"OnCompleteMessage" => "HTMLText",
		"ShowClearButton" => "Boolean",
		'DisableSaveSubmissions' => 'Boolean',
		'EnableLiveValidation' => 'Boolean',
		'HideFieldLabels' => 'Boolean',
		'DisplayErrorMessagesAtTop' => 'Boolean',
		'DisableAuthenicatedFinishAction' => 'Boolean',
		'DisableCsrfSecurityToken' => 'Boolean'
	);

	/**
	 * @var array Default values of variables when this page is created
	 */
	private static $defaults = array(
		'Content' => '$UserDefinedForm',
		'DisableSaveSubmissions' => 0,
		'OnCompleteMessage' => '<p>Thanks, we\'ve received your submission.</p>'
	);

	/**
	 * @var array
	 */
	private static $has_many = array(
		"Submissions" => "SubmittedForm",
		"EmailRecipients" => "UserDefinedForm_EmailRecipient"
	);

	/**
	 * @var array
	 * @config
	 */
	private static $casting = array(
		'ErrorContainerID' => 'Text'
	);

	/**
	 * Error container selector which matches the element for grouped messages
	 *
	 * @var string
	 * @config
	 */
	private static $error_container_id = 'error-container';

	/**
	 * Temporary storage of field ids when the form is duplicated.
	 * Example layout: array('EditableCheckbox3' => 'EditableCheckbox14')
	 * @var array
	 */
	protected $fieldsFromTo = array();

	/**
	 * @return FieldList
	 */
	 public function getCMSFields() {
		Requirements::css(USERFORMS_DIR . '/css/UserForm_cms.css');

		$self = $this;

		$this->beforeUpdateCMSFields(function($fields) use ($self) {

			// define tabs
			$fields->findOrMakeTab('Root.FormOptions', _t('UserDefinedForm.CONFIGURATION', 'Configuration'));
			$fields->findOrMakeTab('Root.Recipients', _t('UserDefinedForm.RECIPIENTS', 'Recipients'));
			$fields->findOrMakeTab('Root.Submissions', _t('UserDefinedForm.SUBMISSIONS', 'Submissions'));

			// text to show on complete
			$onCompleteFieldSet = new CompositeField(
				$label = new LabelField('OnCompleteMessageLabel',_t('UserDefinedForm.ONCOMPLETELABEL', 'Show on completion')),
				$editor = new HtmlEditorField( 'OnCompleteMessage', '', _t('UserDefinedForm.ONCOMPLETEMESSAGE', $self->OnCompleteMessage))
			);

			$onCompleteFieldSet->addExtraClass('field');

			$editor->setRows(3);
			$label->addExtraClass('left');

			// Define config for email recipients
			$emailRecipientsConfig = GridFieldConfig_RecordEditor::create(10);
			$emailRecipientsConfig->getComponentByType('GridFieldAddNewButton')
				->setButtonName(
					_t('UserDefinedForm.ADDEMAILRECIPIENT', 'Add Email Recipient')
				);

			// who do we email on submission
			$emailRecipients = new GridField(
				'EmailRecipients',
				_t('UserDefinedForm.EMAILRECIPIENTS', 'Email Recipients'),
				$self->EmailRecipients(),
				$emailRecipientsConfig
			);
			$emailRecipients
				->getConfig()
				->getComponentByType('GridFieldDetailForm')
				->setItemRequestClass('UserFormRecipientItemRequest');

			$fields->addFieldsToTab('Root.FormOptions', $onCompleteFieldSet);
			$fields->addFieldToTab('Root.Recipients', $emailRecipients);
			$fields->addFieldsToTab('Root.FormOptions', $self->getFormOptions());


			// view the submissions
			$submissions = new GridField(
				'Submissions',
				_t('UserDefinedForm.SUBMISSIONS', 'Submissions'),
				 $self->Submissions()->sort('Created', 'DESC')
			);

			// make sure a numeric not a empty string is checked against this int column for SQL server
			$parentID = (!empty($self->ID)) ? $self->ID : 0;

			// get a list of all field names and values used for print and export CSV views of the GridField below.
			$columnSQL = <<<SQL
SELECT "Name", "Title"
FROM "SubmittedFormField"
LEFT JOIN "SubmittedForm" ON "SubmittedForm"."ID" = "SubmittedFormField"."ParentID"
WHERE "SubmittedForm"."ParentID" = '$parentID'
ORDER BY "Title" ASC
SQL;
			// Sanitise periods in title
			$columns = array();
			foreach(DB::query($columnSQL)->map() as $name => $title) {
				$columns[$name] = trim(strtr($title, '.', ' '));
			}

			$config = new GridFieldConfig();
			$config->addComponent(new GridFieldToolbarHeader());
			$config->addComponent($sort = new GridFieldSortableHeader());
			$config->addComponent($filter = new UserFormsGridFieldFilterHeader());
			$config->addComponent(new GridFieldDataColumns());
			$config->addComponent(new GridFieldEditButton());
			$config->addComponent(new GridFieldDeleteAction());
			$config->addComponent(new GridFieldPageCount('toolbar-header-right'));
			$config->addComponent($pagination = new GridFieldPaginator(25));
			$config->addComponent(new GridFieldDetailForm());
			$config->addComponent(new GridFieldButtonRow('after'));
			$config->addComponent($export = new GridFieldExportButton('buttons-after-left'));
			$config->addComponent($print = new GridFieldPrintButton('buttons-after-left'));

			/**
			 * Support for {@link https://github.com/colymba/GridFieldBulkEditingTools}
			 */
			if(class_exists('GridFieldBulkManager')) {
				$config->addComponent(new GridFieldBulkManager());
			}

			$sort->setThrowExceptionOnBadDataType(false);
			$filter->setThrowExceptionOnBadDataType(false);
			$pagination->setThrowExceptionOnBadDataType(false);

			// attach every column to the print view form
			$columns['Created'] = 'Created';
			$filter->setColumns($columns);

			// print configuration

			$print->setPrintHasHeader(true);
			$print->setPrintColumns($columns);

			// export configuration
			$export->setCsvHasHeader(true);
			$export->setExportColumns($columns);

			$submissions->setConfig($config);
			$fields->addFieldToTab('Root.Submissions', $submissions);
			$fields->addFieldToTab('Root.FormOptions', new CheckboxField('DisableSaveSubmissions', _t('UserDefinedForm.SAVESUBMISSIONS', 'Disable Saving Submissions to Server')));

		});

		$fields = parent::getCMSFields();

		return $fields;
	}

	/**
	 * Allow overriding the EmailRecipients on a {@link DataExtension}
	 * so you can customise who receives an email.
	 * Converts the RelationList to an ArrayList so that manipulation
	 * of the original source data isn't possible.
	 *
	 * @return ArrayList
	 */
	public function FilteredEmailRecipients($data = null, $form = null) {
		$recipients = new ArrayList($this->EmailRecipients()->toArray());

		// Filter by rules
		$recipients = $recipients->filterByCallback(function($recipient) use ($data, $form) {
			return $recipient->canSend($data, $form);
		});

		$this->extend('updateFilteredEmailRecipients', $recipients, $data, $form);

		return $recipients;
	}

	/**
	 * Custom options for the form. You can extend the built in options by
	 * using {@link updateFormOptions()}
	 *
	 * @return FieldList
	 */
	public function getFormOptions() {
		$submit = ($this->SubmitButtonText) ? $this->SubmitButtonText : _t('UserDefinedForm.SUBMITBUTTON', 'Submit');
		$clear = ($this->ClearButtonText) ? $this->ClearButtonText : _t('UserDefinedForm.CLEARBUTTON', 'Clear');

		$options = new FieldList(
			new TextField("SubmitButtonText", _t('UserDefinedForm.TEXTONSUBMIT', 'Text on submit button:'), $submit),
			new TextField("ClearButtonText", _t('UserDefinedForm.TEXTONCLEAR', 'Text on clear button:'), $clear),
			new CheckboxField("ShowClearButton", _t('UserDefinedForm.SHOWCLEARFORM', 'Show Clear Form Button'), $this->ShowClearButton),
			new CheckboxField("EnableLiveValidation", _t('UserDefinedForm.ENABLELIVEVALIDATION', 'Enable live validation')),
			new CheckboxField("HideFieldLabels", _t('UserDefinedForm.HIDEFIELDLABELS', 'Hide field labels')),
			new CheckboxField("DisplayErrorMessagesAtTop", _t('UserDefinedForm.DISPLAYERRORMESSAGESATTOP', 'Display error messages above the form?')),
			new CheckboxField('DisableCsrfSecurityToken', _t('UserDefinedForm.DISABLECSRFSECURITYTOKEN', 'Disable CSRF Token')),
			new CheckboxField('DisableAuthenicatedFinishAction', _t('UserDefinedForm.DISABLEAUTHENICATEDFINISHACTION', 'Disable Authentication on finish action'))
		);

		$this->extend('updateFormOptions', $options);

		return $options;
	}

	/**
	 * Get the HTML id of the error container displayed above the form.
	 *
	 * @return string
	 */
	public function getErrorContainerID() {
		return $this->config()->error_container_id;
	}

	public function requireDefaultRecords() {
		parent::requireDefaultRecords();

		if(!$this->config()->upgrade_on_build) {
			return;
		}

		// Perform migrations
		Injector::inst()
			->create('UserFormsUpgradeService')
			->setQuiet(true)
			->run();

		DB::alteration_message('Migrated userforms', 'changed');
	}


	/**
	 * Validate formfields
	 */
	public function getCMSValidator() {
		return new UserFormValidator();
	}
}

/**
 * Controller for the {@link UserDefinedForm} page type.
 *
 * @package userforms
 */

class UserDefinedForm_Controller extends Page_Controller {

	private static $finished_anchor = '#uff';

	private static $allowed_actions = array(
		'index',
		'ping',
		'Form',
		'finished'
	);

	public function init() {
		parent::init();

		// load the jquery
		$lang = i18n::get_lang_from_locale(i18n::get_locale());
		Requirements::css(USERFORMS_DIR . '/css/UserForm.css');
		Requirements::javascript(FRAMEWORK_DIR .'/thirdparty/jquery/jquery.js');
		Requirements::javascript(USERFORMS_DIR . '/thirdparty/jquery-validate/jquery.validate.min.js');
		Requirements::add_i18n_javascript(USERFORMS_DIR . '/javascript/lang');
		Requirements::javascript(USERFORMS_DIR . '/javascript/UserForm.js');

		Requirements::javascript(
			USERFORMS_DIR . "/thirdparty/jquery-validate/localization/messages_{$lang}.min.js"
		);
		Requirements::javascript(
			USERFORMS_DIR . "/thirdparty/jquery-validate/localization/methods_{$lang}.min.js"
		);
		if($this->HideFieldLabels) {
			Requirements::javascript(USERFORMS_DIR . '/thirdparty/Placeholders.js/Placeholders.min.js');
		}
	}

	/**
	 * Using $UserDefinedForm in the Content area of the page shows
	 * where the form should be rendered into. If it does not exist
	 * then default back to $Form.
	 *
	 * @return array
	 */
	public function index() {
		if($this->Content && $form = $this->Form()) {
			$hasLocation = stristr($this->Content, '$UserDefinedForm');
			if($hasLocation) {
				$content = preg_replace('/(<p[^>]*>)?\\$UserDefinedForm(<\\/p>)?/i', $form->forTemplate(), $this->Content);
				return array(
					'Content' => DBField::create_field('HTMLText', $content),
					'Form' => ""
				);
			}
		}

		return array(
			'Content' => DBField::create_field('HTMLText', $this->Content),
			'Form' => $this->Form()
		);
	}

	/**
	 * Keep the session alive for the user.
	 *
	 * @return int
	 */
	public function ping() {
		return 1;
	}

	/**
	 * Get the form for the page. Form can be modified by calling {@link updateForm()}
	 * on a UserDefinedForm extension.
	 *
	 * @return Forms
	 */
	public function Form() {
		$form = UserForm::create($this);
		$this->generateConditionalJavascript();
		return $form;
	}

	/**
	 * Generate the javascript for the conditional field show / hiding logic.
	 *
	 * @return void
	 */
	public function generateConditionalJavascript() {
		$default = "";
		$rules = "";

		$watch = array();
		$watchLoad = array();

		if($this->Fields()) {
			foreach($this->Fields() as $field) {
				$holderSelector = $field->getSelectorHolder();

				// Is this Field Show by Default
				if(!$field->ShowOnLoad) {
					$default .= "{$holderSelector}.hide().trigger('userform.field.hide');\n";
				}

				// Check for field dependencies / default
				foreach($field->DisplayRules() as $rule) {

					// Get the field which is effected
					$formFieldWatch = EditableFormField::get()->byId($rule->ConditionFieldID);
					
					// Skip deleted fields
					if(!$formFieldWatch) {
						continue;
					}

					$fieldToWatch = $formFieldWatch->getSelectorField($rule);
					$fieldToWatchOnLoad = $formFieldWatch->getSelectorField($rule, true);

					// show or hide?
					$view = ($rule->Display == 'Hide') ? 'hide' : 'show';
					$opposite = ($view == "show") ? "hide" : "show";

					// what action do we need to keep track of. Something nicer here maybe?
					// @todo encapulsation
					$action = "change";

					if($formFieldWatch instanceof EditableTextField) {
						$action = "keyup";
					}

					// is this field a special option field
					$checkboxField = false;<commit_msg>remove trailing spaces in the codebase<commit_after><?php

/**
 * @package userforms
 */

class UserDefinedForm extends Page {

	/**
	 * @var string
	 */
	private static $description = 'Adds a customizable form.';

	/**
	 * @var string Required Identifier
	 */
	private static $required_identifier = null;

	/**
	 * @var string
	 */
	private static $email_template_directory = 'userforms/templates/email/';

	/**
	 * Should this module automatically upgrade on dev/build?
	 *
	 * @config
	 * @var bool
	 */
	private static $upgrade_on_build = true;

	/**
	 * Built in extensions required by this page
	 * @config
	 * @var array
	 */
	private static $extensions = array(
		'UserFormFieldEditorExtension'
	);

	/**
	 * @var array Fields on the user defined form page.
	 */
	private static $db = array(
		"SubmitButtonText" => "Varchar",
		"ClearButtonText" => "Varchar",
		"OnCompleteMessage" => "HTMLText",
		"ShowClearButton" => "Boolean",
		'DisableSaveSubmissions' => 'Boolean',
		'EnableLiveValidation' => 'Boolean',
		'HideFieldLabels' => 'Boolean',
		'DisplayErrorMessagesAtTop' => 'Boolean',
		'DisableAuthenicatedFinishAction' => 'Boolean',
		'DisableCsrfSecurityToken' => 'Boolean'
	);

	/**
	 * @var array Default values of variables when this page is created
	 */
	private static $defaults = array(
		'Content' => '$UserDefinedForm',
		'DisableSaveSubmissions' => 0,
		'OnCompleteMessage' => '<p>Thanks, we\'ve received your submission.</p>'
	);

	/**
	 * @var array
	 */
	private static $has_many = array(
		"Submissions" => "SubmittedForm",
		"EmailRecipients" => "UserDefinedForm_EmailRecipient"
	);

	/**
	 * @var array
	 * @config
	 */
	private static $casting = array(
		'ErrorContainerID' => 'Text'
	);

	/**
	 * Error container selector which matches the element for grouped messages
	 *
	 * @var string
	 * @config
	 */
	private static $error_container_id = 'error-container';

	/**
	 * Temporary storage of field ids when the form is duplicated.
	 * Example layout: array('EditableCheckbox3' => 'EditableCheckbox14')
	 * @var array
	 */
	protected $fieldsFromTo = array();

	/**
	 * @return FieldList
	 */
	 public function getCMSFields() {
		Requirements::css(USERFORMS_DIR . '/css/UserForm_cms.css');

		$self = $this;

		$this->beforeUpdateCMSFields(function($fields) use ($self) {

			// define tabs
			$fields->findOrMakeTab('Root.FormOptions', _t('UserDefinedForm.CONFIGURATION', 'Configuration'));
			$fields->findOrMakeTab('Root.Recipients', _t('UserDefinedForm.RECIPIENTS', 'Recipients'));
			$fields->findOrMakeTab('Root.Submissions', _t('UserDefinedForm.SUBMISSIONS', 'Submissions'));

			// text to show on complete
			$onCompleteFieldSet = new CompositeField(
				$label = new LabelField('OnCompleteMessageLabel',_t('UserDefinedForm.ONCOMPLETELABEL', 'Show on completion')),
				$editor = new HtmlEditorField( 'OnCompleteMessage', '', _t('UserDefinedForm.ONCOMPLETEMESSAGE', $self->OnCompleteMessage))
			);

			$onCompleteFieldSet->addExtraClass('field');

			$editor->setRows(3);
			$label->addExtraClass('left');

			// Define config for email recipients
			$emailRecipientsConfig = GridFieldConfig_RecordEditor::create(10);
			$emailRecipientsConfig->getComponentByType('GridFieldAddNewButton')
				->setButtonName(
					_t('UserDefinedForm.ADDEMAILRECIPIENT', 'Add Email Recipient')
				);

			// who do we email on submission
			$emailRecipients = new GridField(
				'EmailRecipients',
				_t('UserDefinedForm.EMAILRECIPIENTS', 'Email Recipients'),
				$self->EmailRecipients(),
				$emailRecipientsConfig
			);
			$emailRecipients
				->getConfig()
				->getComponentByType('GridFieldDetailForm')
				->setItemRequestClass('UserFormRecipientItemRequest');

			$fields->addFieldsToTab('Root.FormOptions', $onCompleteFieldSet);
			$fields->addFieldToTab('Root.Recipients', $emailRecipients);
			$fields->addFieldsToTab('Root.FormOptions', $self->getFormOptions());


			// view the submissions
			$submissions = new GridField(
				'Submissions',
				_t('UserDefinedForm.SUBMISSIONS', 'Submissions'),
				 $self->Submissions()->sort('Created', 'DESC')
			);

			// make sure a numeric not a empty string is checked against this int column for SQL server
			$parentID = (!empty($self->ID)) ? $self->ID : 0;

			// get a list of all field names and values used for print and export CSV views of the GridField below.
			$columnSQL = <<<SQL
SELECT "Name", "Title"
FROM "SubmittedFormField"
LEFT JOIN "SubmittedForm" ON "SubmittedForm"."ID" = "SubmittedFormField"."ParentID"
WHERE "SubmittedForm"."ParentID" = '$parentID'
ORDER BY "Title" ASC
SQL;
			// Sanitise periods in title
			$columns = array();
			foreach(DB::query($columnSQL)->map() as $name => $title) {
				$columns[$name] = trim(strtr($title, '.', ' '));
			}

			$config = new GridFieldConfig();
			$config->addComponent(new GridFieldToolbarHeader());
			$config->addComponent($sort = new GridFieldSortableHeader());
			$config->addComponent($filter = new UserFormsGridFieldFilterHeader());
			$config->addComponent(new GridFieldDataColumns());
			$config->addComponent(new GridFieldEditButton());
			$config->addComponent(new GridFieldDeleteAction());
			$config->addComponent(new GridFieldPageCount('toolbar-header-right'));
			$config->addComponent($pagination = new GridFieldPaginator(25));
			$config->addComponent(new GridFieldDetailForm());
			$config->addComponent(new GridFieldButtonRow('after'));
			$config->addComponent($export = new GridFieldExportButton('buttons-after-left'));
			$config->addComponent($print = new GridFieldPrintButton('buttons-after-left'));

			/**
			 * Support for {@link https://github.com/colymba/GridFieldBulkEditingTools}
			 */
			if(class_exists('GridFieldBulkManager')) {
				$config->addComponent(new GridFieldBulkManager());
			}

			$sort->setThrowExceptionOnBadDataType(false);
			$filter->setThrowExceptionOnBadDataType(false);
			$pagination->setThrowExceptionOnBadDataType(false);

			// attach every column to the print view form
			$columns['Created'] = 'Created';
			$filter->setColumns($columns);

			// print configuration

			$print->setPrintHasHeader(true);
			$print->setPrintColumns($columns);

			// export configuration
			$export->setCsvHasHeader(true);
			$export->setExportColumns($columns);

			$submissions->setConfig($config);
			$fields->addFieldToTab('Root.Submissions', $submissions);
			$fields->addFieldToTab('Root.FormOptions', new CheckboxField('DisableSaveSubmissions', _t('UserDefinedForm.SAVESUBMISSIONS', 'Disable Saving Submissions to Server')));

		});

		$fields = parent::getCMSFields();

		return $fields;
	}

	/**
	 * Allow overriding the EmailRecipients on a {@link DataExtension}
	 * so you can customise who receives an email.
	 * Converts the RelationList to an ArrayList so that manipulation
	 * of the original source data isn't possible.
	 *
	 * @return ArrayList
	 */
	public function FilteredEmailRecipients($data = null, $form = null) {
		$recipients = new ArrayList($this->EmailRecipients()->toArray());

		// Filter by rules
		$recipients = $recipients->filterByCallback(function($recipient) use ($data, $form) {
			return $recipient->canSend($data, $form);
		});

		$this->extend('updateFilteredEmailRecipients', $recipients, $data, $form);

		return $recipients;
	}

	/**
	 * Custom options for the form. You can extend the built in options by
	 * using {@link updateFormOptions()}
	 *
	 * @return FieldList
	 */
	public function getFormOptions() {
		$submit = ($this->SubmitButtonText) ? $this->SubmitButtonText : _t('UserDefinedForm.SUBMITBUTTON', 'Submit');
		$clear = ($this->ClearButtonText) ? $this->ClearButtonText : _t('UserDefinedForm.CLEARBUTTON', 'Clear');

		$options = new FieldList(
			new TextField("SubmitButtonText", _t('UserDefinedForm.TEXTONSUBMIT', 'Text on submit button:'), $submit),
			new TextField("ClearButtonText", _t('UserDefinedForm.TEXTONCLEAR', 'Text on clear button:'), $clear),
			new CheckboxField("ShowClearButton", _t('UserDefinedForm.SHOWCLEARFORM', 'Show Clear Form Button'), $this->ShowClearButton),
			new CheckboxField("EnableLiveValidation", _t('UserDefinedForm.ENABLELIVEVALIDATION', 'Enable live validation')),
			new CheckboxField("HideFieldLabels", _t('UserDefinedForm.HIDEFIELDLABELS', 'Hide field labels')),
			new CheckboxField("DisplayErrorMessagesAtTop", _t('UserDefinedForm.DISPLAYERRORMESSAGESATTOP', 'Display error messages above the form?')),
			new CheckboxField('DisableCsrfSecurityToken', _t('UserDefinedForm.DISABLECSRFSECURITYTOKEN', 'Disable CSRF Token')),
			new CheckboxField('DisableAuthenicatedFinishAction', _t('UserDefinedForm.DISABLEAUTHENICATEDFINISHACTION', 'Disable Authentication on finish action'))
		);

		$this->extend('updateFormOptions', $options);

		return $options;
	}

	/**
	 * Get the HTML id of the error container displayed above the form.
	 *
	 * @return string
	 */
	public function getErrorContainerID() {
		return $this->config()->error_container_id;
	}

	public function requireDefaultRecords() {
		parent::requireDefaultRecords();

		if(!$this->config()->upgrade_on_build) {
			return;
		}

		// Perform migrations
		Injector::inst()
			->create('UserFormsUpgradeService')
			->setQuiet(true)
			->run();

		DB::alteration_message('Migrated userforms', 'changed');
	}


	/**
	 * Validate formfields
	 */
	public function getCMSValidator() {
		return new UserFormValidator();
	}
}

/**
 * Controller for the {@link UserDefinedForm} page type.
 *
 * @package userforms
 */

class UserDefinedForm_Controller extends Page_Controller {

	private static $finished_anchor = '#uff';

	private static $allowed_actions = array(
		'index',
		'ping',
		'Form',
		'finished'
	);

	public function init() {
		parent::init();

		// load the jquery
		$lang = i18n::get_lang_from_locale(i18n::get_locale());
		Requirements::css(USERFORMS_DIR . '/css/UserForm.css');
		Requirements::javascript(FRAMEWORK_DIR .'/thirdparty/jquery/jquery.js');
		Requirements::javascript(USERFORMS_DIR . '/thirdparty/jquery-validate/jquery.validate.min.js');
		Requirements::add_i18n_javascript(USERFORMS_DIR . '/javascript/lang');
		Requirements::javascript(USERFORMS_DIR . '/javascript/UserForm.js');

		Requirements::javascript(
			USERFORMS_DIR . "/thirdparty/jquery-validate/localization/messages_{$lang}.min.js"
		);
		Requirements::javascript(
			USERFORMS_DIR . "/thirdparty/jquery-validate/localization/methods_{$lang}.min.js"
		);
		if($this->HideFieldLabels) {
			Requirements::javascript(USERFORMS_DIR . '/thirdparty/Placeholders.js/Placeholders.min.js');
		}
	}

	/**
	 * Using $UserDefinedForm in the Content area of the page shows
	 * where the form should be rendered into. If it does not exist
	 * then default back to $Form.
	 *
	 * @return array
	 */
	public function index() {
		if($this->Content && $form = $this->Form()) {
			$hasLocation = stristr($this->Content, '$UserDefinedForm');
			if($hasLocation) {
				$content = preg_replace('/(<p[^>]*>)?\\$UserDefinedForm(<\\/p>)?/i', $form->forTemplate(), $this->Content);
				return array(
					'Content' => DBField::create_field('HTMLText', $content),
					'Form' => ""
				);
			}
		}

		return array(
			'Content' => DBField::create_field('HTMLText', $this->Content),
			'Form' => $this->Form()
		);
	}

	/**
	 * Keep the session alive for the user.
	 *
	 * @return int
	 */
	public function ping() {
		return 1;
	}

	/**
	 * Get the form for the page. Form can be modified by calling {@link updateForm()}
	 * on a UserDefinedForm extension.
	 *
	 * @return Forms
	 */
	public function Form() {
		$form = UserForm::create($this);
		$this->generateConditionalJavascript();
		return $form;
	}

	/**
	 * Generate the javascript for the conditional field show / hiding logic.
	 *
	 * @return void
	 */
	public function generateConditionalJavascript() {
		$default = "";
		$rules = "";

		$watch = array();
		$watchLoad = array();

		if($this->Fields()) {
			foreach($this->Fields() as $field) {
				$holderSelector = $field->getSelectorHolder();

				// Is this Field Show by Default
				if(!$field->ShowOnLoad) {
					$default .= "{$holderSelector}.hide().trigger('userform.field.hide');\n";
				}

				// Check for field dependencies / default
				foreach($field->DisplayRules() as $rule) {

					// Get the field which is effected
					$formFieldWatch = EditableFormField::get()->byId($rule->ConditionFieldID);

					// Skip deleted fields
					if(!$formFieldWatch) {
						continue;
					}

					$fieldToWatch = $formFieldWatch->getSelectorField($rule);
					$fieldToWatchOnLoad = $formFieldWatch->getSelectorField($rule, true);

					// show or hide?
					$view = ($rule->Display == 'Hide') ? 'hide' : 'show';
					$opposite = ($view == "show") ? "hide" : "show";

					// what action do we need to keep track of. Something nicer here maybe?
					// @todo encapulsation
					$action = "change";

					if($formFieldWatch instanceof EditableTextField) {
						$action = "keyup";
					}

					// is this field a special option field
					$checkboxField = false;
{'fraction_non_alphanumeric': 0.14804533888503354, 'fraction_numerical': 0.0013108181047112345, 'mean_word_length': 4.407337919533042, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 225, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, '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': '3804812', 'n_tokens_mistral': 9030, 'n_tokens_neox': 7758, 'n_words': 1752}