<?php

declare(strict_types=1);

/**
 * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
 * SPDX-License-Identifier: AGPL-3.0-or-later
 */
namespace OCA\WorkflowEngine\Settings;

use OCA\WorkflowEngine\AppInfo\Application;
use OCA\WorkflowEngine\Manager;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Services\IInitialState;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\IConfig;
use OCP\IL10N;
use OCP\IURLGenerator;
use OCP\Settings\ISettings;
use OCP\WorkflowEngine\Events\LoadSettingsScriptsEvent;
use OCP\WorkflowEngine\ICheck;
use OCP\WorkflowEngine\IComplexOperation;
use OCP\WorkflowEngine\IEntity;
use OCP\WorkflowEngine\IEntityEvent;
use OCP\WorkflowEngine\IOperation;
use OCP\WorkflowEngine\ISpecificOperation;

abstract class ASettings implements ISettings {
	private IL10N $l10n;
	private string $appName;
	private IEventDispatcher $eventDispatcher;
	protected Manager $manager;
	private IInitialState $initialStateService;
	private IConfig $config;
	private IURLGenerator $urlGenerator;

	public function __construct(
		string $appName,
		IL10N $l,
		IEventDispatcher $eventDispatcher,
		Manager $manager,
		IInitialState $initialStateService,
		IConfig $config,
		IURLGenerator $urlGenerator
	) {
		$this->appName = $appName;
		$this->l10n = $l;
		$this->eventDispatcher = $eventDispatcher;
		$this->manager = $manager;
		$this->initialStateService = $initialStateService;
		$this->config = $config;
		$this->urlGenerator = $urlGenerator;
	}

	abstract public function getScope(): int;

	/**
	 * @return TemplateResponse
	 */
	public function getForm(): TemplateResponse {
		// @deprecated in 20.0.0: retire this one in favor of the typed event
		$this->eventDispatcher->dispatch(
			'OCP\WorkflowEngine::loadAdditionalSettingScripts',
			new LoadSettingsScriptsEvent()
		);
		$this->eventDispatcher->dispatchTyped(new LoadSettingsScriptsEvent());

		$entities = $this->manager->getEntitiesList();
		$this->initialStateService->provideInitialState(
			'entities',
			$this->entitiesToArray($entities)
		);

		$operators = $this->manager->getOperatorList();
		$this->initialStateService->provideInitialState(
			'operators',
			$this->operatorsToArray($operators)
		);

		$checks = $this->manager->getCheckList();
		$this->initialStateService->provideInitialState(
			'checks',
			$this->checksToArray($checks)
		);

		$this->initialStateService->provideInitialState(
			'scope',
			$this->getScope()
		);

		$this->initialStateService->provideInitialState(
			'appstoreenabled',
			$this->config->getSystemValueBool('appstoreenabled', true)
		);

		$this->initialStateService->provideInitialState(
			'doc-url',
			$this->urlGenerator->linkToDocs('admin-workflowengine')
		);

		return new TemplateResponse(Application::APP_ID, 'settings', [], 'blank');
	}

	/**
	 * @return string the section ID, e.g. 'sharing'
	 */
	public function getSection(): ?string {
		return 'workflow';
	}

	/**
	 * @return int whether the form should be rather on the top or bottom of
	 *             the admin section. The forms are arranged in ascending order of the
	 *             priority values. It is required to return a value between 0 and 100.
	 *
	 * E.g.: 70
	 */
	public function getPriority(): int {
		return 0;
	}

	private function entitiesToArray(array $entities) {
		return array_map(function (IEntity $entity) {
			$events = array_map(function (IEntityEvent $entityEvent) {
				return [
					'eventName' => $entityEvent->getEventName(),
					'displayName' => $entityEvent->getDisplayName()
				];
			}, $entity->getEvents());

			return [
				'id' => get_class($entity),
				'icon' => $entity->getIcon(),
				'name' => $entity->getName(),
				'events' => $events,
			];
		}, $entities);
	}

	private function operatorsToArray(array $operators) {
		$operators = array_filter($operators, function (IOperation $operator) {
			return $operator->isAvailableForScope($this->getScope());
		});

		return array_map(function (IOperation $operator) {
			return [
				'id' => get_class($operator),
				'icon' => $operator->getIcon(),
				'name' => $operator->getDisplayName(),
				'description' => $operator->getDescription(),
				'fixedEntity' => $operator instanceof ISpecificOperation ? $operator->getEntityId() : '',
				'isComplex' => $operator instanceof IComplexOperation,
				'triggerHint' => $operator instanceof IComplexOperation ? $operator->getTriggerHint() : '',
			];
		}, $operators);
	}

	private function checksToArray(array $checks) {
		$checks = array_filter($checks, function (ICheck $check) {
			return $check->isAvailableForScope($this->getScope());
		});

		return array_map(function (ICheck $check) {
			return [
				'id' => get_class($check),
				'supportedEntities' => $check->supportedEntities(),
			];
		}, $checks);
	}
}
eature/vaadin8-book</option>
<option value='feature/vaadin8-book-vol2'>feature/vaadin8-book-vol2</option>
<option value='feature/vaadin8-sass-valo-only'>feature/vaadin8-sass-valo-only</option>
<option value='fileToFilesReplacement'>fileToFilesReplacement</option>
<option value='fix11576'>fix11576</option>
<option value='fix_event_router_prototype'>fix_event_router_prototype</option>
<option value='grid'>grid</option>
<option value='grid_dnd_autoscroller'>grid_dnd_autoscroller</option>
<option value='grid_dragger'>grid_dragger</option>
<option value='issue/8307_select_using_collection'>issue/8307_select_using_collection</option>
<option value='master'>master</option>
<option value='mobile_drag_image_offset'>mobile_drag_image_offset</option>
<option value='pr/11306'>pr/11306</option>
<option value='remote-run/flow-atmosphere-test'>remote-run/flow-atmosphere-test</option>
<option value='snapshot/7.5'>snapshot/7.5</option>
<option value='snapshot/7.6'>snapshot/7.6</option>
<option value='tmattsso-patch-1'>tmattsso-patch-1</option>
<option value='update-minor-deps'>update-minor-deps</option>
<option value='vaadin-icons-3.0.1'>vaadin-icons-3.0.1</option>
<option value='wip-date-time-datatype'>wip-date-time-datatype</option>
<option value='wip-java-10-compat'>wip-java-10-compat</option>
</select> <input type='submit' value='switch'/></form></td></tr>
<tr><td class='sub'>Vaadin 6, 7, 8 is a Java framework for modern Java web applications: https://github.com/vaadin/framework</td><td class='sub right'>www-data</td></tr></table>
<table class='tabs'><tr><td>
<a href='/vaadin-framework.git/about/?h=JS-RPC-docs-link-syntax'>about</a><a href='/vaadin-framework.git/?h=JS-RPC-docs-link-syntax'>summary</a><a href='/vaadin-framework.git/refs/?h=JS-RPC-docs-link-syntax&amp;id=aa225cce86d34fc656e091f5eb62f73d17351345'>refs</a><a href='/vaadin-framework.git/log/documentation/articles/UsingURIFragments.asciidoc?h=JS-RPC-docs-link-syntax'>log</a><a class='active' href='/vaadin-framework.git/tree/documentation/articles/UsingURIFragments.asciidoc?h=JS-RPC-docs-link-syntax&amp;id=aa225cce86d34fc656e091f5eb62f73d17351345'>tree</a><a href='/vaadin-framework.git/commit/documentation/articles/UsingURIFragments.asciidoc?h=JS-RPC-docs-link-syntax&amp;id=aa225cce86d34fc656e091f5eb62f73d17351345'>commit</a><a href='/vaadin-framework.git/diff/documentation/articles/UsingURIFragments.asciidoc?h=JS-RPC-docs-link-syntax&amp;id=aa225cce86d34fc656e091f5eb62f73d17351345'>diff</a><a href='/vaadin-framework.git/stats/documentation/articles/UsingURIFragments.asciidoc?h=JS-RPC-docs-link-syntax'>stats</a></td><td class='form'><form class='right' method='get' action='/vaadin-framework.git/log/documentation/articles/UsingURIFragments.asciidoc'>
<input type='hidden' name='h' value='JS-RPC-docs-link-syntax'/><input type='hidden' name='id' value='aa225cce86d34fc656e091f5eb62f73d17351345'/><select name='qt'>
<option value='grep'>log msg</option>
<option value='author'>author</option>
<option value='committer'>committer</option>
<option value='range'>range</option>
</select>
<input class='txt' type='search' size='10' name='q' value=''/>
<input type='submit' value='search'/>
</form>
</td></tr></table>
<div class='path'>path: <a href='/vaadin-framework.git/tree/?h=JS-RPC-docs-link-syntax&amp;id=aa225cce86d34fc656e091f5eb62f73d17351345'>root</a>/<a href='/vaadin-framework.git/tree/documentation?h=JS-RPC-docs-link-syntax&amp;id=aa225cce86d34fc656e091f5eb62f73d17351345'>documentation</a>/<a href='/vaadin-framework.git/tree/documentation/articles?h=JS-RPC-docs-link-syntax&amp;id=aa225cce86d34fc656e091f5eb62f73d17351345'>articles</a>/<a href='/vaadin-framework.git/tree/documentation/articles/UsingURIFragments.asciidoc?h=JS-RPC-docs-link-syntax&amp;id=aa225cce86d34fc656e091f5eb62f73d17351345'>UsingURIFragments.asciidoc</a></div><div class='content'>blob: eebdf783032640d07c861b0b7ddb77947ab15b0c (<a href='/vaadin-framework.git/plain/documentation/articles/UsingURIFragments.asciidoc?h=JS-RPC-docs-link-syntax&amp;id=aa225cce86d34fc656e091f5eb62f73d17351345'>plain</a>)
<table summary='blob content' class='blob'>
<tr><td class='linenumbers'><pre><a id='n1' href='#n1'>1</a>
<a id='n2' href='#n2'>2</a>
<a id='n3' href='#n3'>3</a>
<a id='n4' href='#n4'>4</a>
<a id='n5' href='#n5'>5</a>
<a id='n6' href='#n6'>6</a>
<a id='n7' href='#n7'>7</a>
<a id='n8' href='#n8'>8</a>
<a id='n9' href='#n9'>9</a>
<a id='n10' href='#n10'>10</a>
<a id='n11' href='#n11'>11</a>
<a id='n12' href='#n12'>12</a>
<a id='n13' href='#n13'>13</a>
<a id='n14' href='#n14'>14</a>
<a id='n15' href='#n15'>15</a>
<a id='n16' href='#n16'>16</a>
<a id='n17' href='#n17'>17</a>
<a id='n18' href='#n18'>18</a>
<a id='n19' href='#n19'>19</a>
<a id='n20' href='#n20'>20</a>
<a id='n21' href='#n21'>21</a>
<a id='n22' href='#n22'>22</a>
<a id='n23' href='#n23'>23</a>
<a id='n24' href='#n24'>24</a>
<a id='n25' href='#n25'>25</a>
<a id='n26' href='#n26'>26</a>
<a id='n27' href='#n27'>27</a>
<a id='n28' href='#n28'>28</a>
<a id='n29' href='#n29'>29</a>
<a id='n30' href='#n30'>30</a>
<a id='n31' href='#n31'>31</a>
<a id='n32' href='#n32'>32</a>
<a id='n33' href='#n33'>33</a>
<a id='n34' href='#n34'>34</a>
<a id='n35' href='#n35'>35</a>
<a id='n36' href='#n36'>36</a>
<a id='n37' href='#n37'>37</a>
<a id='n38' href='#n38'>38</a>
<a id='n39' href='#n39'>39</a>
<a id='n40' href='#n40'>40</a>
<a id='n41' href='#n41'>41</a>
<a id='n42' href='#n42'>42</a>
<a id='n43' href='#n43'>43</a>
<a id='n44' href='#n44'>44</a>
<a id='n45' href='#n45'>45</a>
<a id='n46' href='#n46'>46</a>
<a id='n47' href='#n47'>47</a>
<a id='n48' href='#n48'>48</a>
<a id='n49' href='#n49'>49</a>
<a id='n50' href='#n50'>50</a>
<a id='n51' href='#n51'>51</a>
<a id='n52' href='#n52'>52</a>
<a id='n53' href='#n53'>53</a>
<a id='n54' href='#n54'>54</a>
<a id='n55' href='#n55'>55</a>
<a id='n56' href='#n56'>56</a>
<a id='n57' href='#n57'>57</a>
<a id='n58' href='#n58'>58</a>
<a id='n59' href='#n59'>59</a>
<a id='n60' href='#n60'>60</a>
<a id='n61' href='#n61'>61</a>
<a id='n62' href='#n62'>62</a>
<a id='n63' href='#n63'>63</a>
<a id='n64' href='#n64'>64</a>
<a id='n65' href='#n65'>65</a>
<a id='n66' href='#n66'>66</a>
<a id='n67' href='#n67'>67</a>
<a id='n68' href='#n68'>68</a>
<a id='n69' href='#n69'>69</a>
<a id='n70' href='#n70'>70</a>
<a id='n71' href='#n71'>71</a>
<a id='n72' href='#n72'>72</a>
<a id='n73' href='#n73'>73</a>
<a id='n74' href='#n74'>74</a>
<a id='n75' href='#n75'>75</a>
<a id='n76' href='#n76'>76</a>
<a id='n77' href='#n77'>77</a>
<a id='n78' href='#n78'>78</a>
<a id='n79' href='#n79'>79</a>
<a id='n80' href='#n80'>80</a>
<a id='n81' href='#n81'>81</a>
<a id='n82' href='#n82'>82</a>
<a id='n83' href='#n83'>83</a>
<a id='n84' href='#n84'>84</a>
<a id='n85' href='#n85'>85</a>
<a id='n86' href='#n86'>86</a>
<a id='n87' href='#n87'>87</a>
</pre></td>
<td class='lines'><pre><code><style>pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */</style><div class="highlight"><pre><span></span>[[using-uri-fragments]]
Using URI fragments
-------------------

[[reading-fragment-when-initializing-ui]]
Reading Fragment when Initializing UI
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

URI fragments can either be used for initializing the UI and/or read or
modified in any listener. In the UI.init method you get a &quot;VaadinRequest
request&quot; parameter. The UI&#39;s Page contains a information about the HTTP
request used to initialize the application and you can get the URI
fragment using

....
getPage().geUriFragment()
....

A simple init that depends on the URI fragment is thus:

[source,java]
....
public class MyUI extends UI {
  @Override
  protected void init(VaadinRequest request) {
    layout = new VerticalLayout();
    layout.setMargin(true);
    setContent(layout);

    Label label = new Label(&quot;Hello, your fragment is &quot;
            + getPage().getUriFragment());
    layout.addComponent(label);
  }
}
....

[[reading-fragment-changes]]
Reading Fragment Changes
~~~~~~~~~~~~~~~~~~~~~~~~

The URI fragment can be changed also when the application is running,
either manually in the location bar in browser or from user code. These
changes can be caught with a **FragmentChangedListener**. Notice,
however, that there is no event fired for the initial URL fragment. The
easiest way to handle both cases in the same way is to call the same
method from the FragmentChangedListener and the init method:

[source,java]
....
public class MyUI extends UI {
  // ...

  // React to fragment changes
  getPage().addUriFragmentChangedListener(new UriFragmentChangedListener() {
    @Override
    public void uriFragmentChanged(UriFragmentChangedEvent source) {
      handleFragment(source.getUriFragment());
    }
  });

  // Handle the fragment received in the initial request
  handleFragment(getPage().getUriFragment());

  addComponent(new Button(&quot;Show and set fragment&quot;, new Button.ClickListener() {
    @Override
      public void buttonClick(ClickEvent event) {
        handleFragment(getPage().getUriFragment());
        getPage().setUriFragment(&quot;customFragment&quot;);
      }
  }));
....

[[reading-and-writing-the-fragment]]
Reading and Writing the Fragment
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

To later on read the fragment you can use

....
Page.getCurrent().getUriFragment();
....

and to set the fragment

....
Page.getCurrent().setUriFragment(String fragment);
....
</pre></div>
</code></pre></td></tr></table>
</div> <!-- class=content -->
<div class='footer'>generated by <a href='https://git.zx2c4.com/cgit/about/'>cgit v1.2.3</a> (<a href='https://git-scm.com/'>git 2.39.1</a>) at 2025-07-24 06:35:07 +0000</div>
</div> <!-- id=cgit -->
</body>
</html>
