Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ This module provides an easy way to build such tree and to add it to a page as a

## Requirements

* SilverStripe 5.x
* SilverStripe 6.x
* (dnadesign/silvertsripe-elemental)[https://github.com/dnadesign/silverstripe-elemental]

## Screenshots
Expand Down
6 changes: 3 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
"minimum-stability": "dev",
"prefer-stable": true,
"require": {
"dnadesign/silverstripe-elemental": "^5",
"silvershop/silverstripe-hasonefield": "^4",
"unclecheese/display-logic": "^3"
"dnadesign/silverstripe-elemental": "^6",
"silvershop/silverstripe-hasonefield": "^5",
"unclecheese/display-logic": "^4"
},
"config": {
"allow-plugins": {
Expand Down
91 changes: 42 additions & 49 deletions src/Extensions/ElementDecisionTreeController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,33 @@

namespace DNADesign\SilverStripeElementalDecisionTree\Extensions;

use DNADesign\SilverStripeElementalDecisionTree\Model\DecisionTreeAnswer;
use DNADesign\SilverStripeElementalDecisionTree\Model\DecisionTreeStep;
use SilverStripe\Control\Controller;
use SilverStripe\View\ArrayData;
use SilverStripe\View\Requirements;
use SilverStripe\Core\Extension;
use DNADesign\SilverStripeElementalDecisionTree\Model\DecisionTreeStep;
use DNADesign\SilverStripeElementalDecisionTree\Model\DecisionTreeAnswer;
use SilverStripe\Model\ArrayData;
use SilverStripe\ORM\FieldType\DBHTMLText;
use SilverStripe\View\Requirements;

class ElementDecisionTreeController extends Extension
{

private static $allowed_actions = [
'getNextStepForAnswer'
private static array $allowed_actions = [
'getNextStepForAnswer',
];

public function onAfterInit()
public function onAfterInit(): void
{
Requirements::javascript('dnadesign/silverstripe-elemental-decisiontree:javascript/decision-tree.src.js');
}

/**
* Return the HTMl for the next step to be displayed
* as well as the updated URL which includes the ids of the answers
* leading to this next step to be returned
*
* @param stepanswerid (POST)
* @return json
*/
public function getNextStepForAnswer()
* Return the HTMl for the next step to be displayed
* as well as the updated URL which includes the ids of the answers
* leading to this next step to be returned.
*
* @param stepanswerid (POST)
*/
public function getNextStepForAnswer(): null|bool|string|DBHTMLText
{
$answerID = $this->owner->getRequest()->postVar('stepanswerid');

Expand All @@ -41,7 +40,7 @@ public function getNextStepForAnswer()

if (!$answer || !$answer->exists()) {
return $this->owner->httpError(
404,
404,
$this->renderError('An error has occurred, please reload the page and try again!')
);
}
Expand All @@ -50,26 +49,27 @@ public function getNextStepForAnswer()

if (!$nextStep || !$nextStep->exists()) {
return $this->owner->httpError(
404,
404,
$this->renderError('An error has occurred, please reload the page and try again!')
);
}

$html = $this->owner->customise(new ArrayData([
'Step' => $nextStep,
'Controller' => $this->owner
'Controller' => $this->owner,
]))->renderWith('DNADesign\SilverStripeElementalDecisionTree\Model\DecisionTreeStep');

$pathway = $nextStep->getAnswerPathway();

$nextURL = Controller::join_links(
$this->owner->AbsoluteLink(), '?decisionpathway='.implode(',', $pathway)
$this->owner->AbsoluteLink(),
'?decisionpathway=' . implode(',', $pathway)
);

if ($this->owner->getRequest()->isAjax()) {
$data = [
'html' => $html->forTemplate(),
'nexturl' => $nextURL
'nexturl' => $nextURL,
];

return json_encode($data);
Expand All @@ -79,12 +79,10 @@ public function getNextStepForAnswer()
}

/**
* Returns an array of DecisionStepID from the URL param
* in order to display the same question when we reload the page
*
* @return Array
*/
public function getInitialPathway()
* Returns an array of DecisionStepID from the URL param
* in order to display the same question when we reload the page.
*/
public function getInitialPathway(): ?array
{
$ids = $this->owner->getRequest()->getVar('decisionpathway');

Expand All @@ -96,12 +94,12 @@ public function getInitialPathway()
}

/**
* Check if an answer should be selected by default
* ie. The question depending on it is displayed
*
* @return Boolean
*/
public function getIsAnswerSelected($answerID)
* Check if an answer should be selected by default
* ie. The question depending on it is displayed.
*
* @param mixed $answerID
*/
public function getIsAnswerSelected($answerID): bool
{
if ($pathway = $this->getInitialPathway()) {
return in_array($answerID, $pathway);
Expand All @@ -111,16 +109,16 @@ public function getIsAnswerSelected($answerID)
}

/**
* Gets the next step to be displayed in regards to the selected answer.
* Used by template to display all the relevant steps from the URL
*
* @return DecisionTreeStep
*/
public function getNextStepFromSelectedAnswer($stepID)
* Gets the next step to be displayed in regards to the selected answer.
* Used by template to display all the relevant steps from the URL.
*
* @param mixed $stepID
*/
public function getNextStepFromSelectedAnswer($stepID): ?DecisionTreeStep
{
$step = DecisionTreeStep::get()->byID($stepID);
if ($step->exists()) {
foreach($step->Answers() as $answer) {
foreach ($step->Answers() as $answer) {
if ($this->getIsAnswerSelected($answer->ID)) {
if ($nextStep = $answer->ResultingStep()) {
return $nextStep;
Expand All @@ -133,13 +131,9 @@ public function getNextStepFromSelectedAnswer($stepID)
}

/**
* Template returned via ajax in case of an error occuring.
*
* @param string
*
* @return string
*/
protected function renderError($message = '')
* Template returned via ajax in case of an error occuring.
*/
protected function renderError(string $message = ''): string
{
return sprintf(
'<div class="step step--error">
Expand All @@ -148,9 +142,8 @@ protected function renderError($message = '')
<span class="step-title">Sorry!</span>
<span class="step-content"><p>%s</p></span>
</div>
</div>',
</div>',
$message
);
}

}
10 changes: 5 additions & 5 deletions src/Forms/DecisionTreeStepPreview.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,30 @@

namespace DNADesign\SilverStripeElementalDecisionTree\Forms;

use DNADesign\SilverStripeElementalDecisionTree\Model\DecisionTreeStep;
use SilverStripe\Forms\FormField;

/**
* This form field is used to display the DecisionTree in the edit form of any
* ElementDecisionTree or DecisionTreeStes. It provides a visual way of
* navigating the tree as well as links to edit/add steps.
*/

class DecisionTreeStepPreview extends FormField
{
protected $step = null;
protected ?DecisionTreeStep $step = null;

public function __construct($name, $step = null)
public function __construct($name, ?DecisionTreeStep $step = null)
{
$this->step = $step;
parent::__construct($name);
}

public function getStep()
public function getStep(): ?DecisionTreeStep
{
return $this->step;
}

public function setStep($step)
public function setStep(?DecisionTreeStep $step): static
{
$this->step = $step;

Expand Down
50 changes: 24 additions & 26 deletions src/Forms/HasOneSelectOrCreateField.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,31 @@

namespace DNADesign\SilverStripeElementalDecisionTree\Forms;

use SilverShop\HasOneField\GridFieldHasOneEditButton;
use SilverShop\HasOneField\HasOneButtonField;
use SilverStripe\Forms\CompositeField;
use SilverStripe\Forms\DropdownField;
use SilverStripe\Forms\FormField;
use SilverShop\HasOneField\HasOneButtonField;
use SilverShop\HasOneField\GridFieldHasOneEditButton;
/**
* This a wrapper for a slightly enhanced user experience when using the
* HasOneButtonField class.
* By default, the HasOneButtonField only allow to create or edit the has_one object
* This class adds a dropdown to allow to select another object or remove the relation
* without deleting the object itself.
* Both fields are wrapped in a CompositeField.
*
* @param String | Name of the has_one relationship
* @param String | Title of the drodpwon field
* @param FieldList or Array | Options listed in the dropdown
* @param Object | Current has_one object, if exists
* @param Object | The object calling this field, required by HasOneButtonField
*/

/**
* This a wrapper for a slightly enhanced user experience when using the
* HasOneButtonField class.
* By default, the HasOneButtonField only allow to create or edit the has_one object
* This class adds a dropdown to allow to select another object or remove the relation
* without deleting the object itself.
* Both fields are wrapped in a CompositeField.
*
* @param Name|string of the has_one relationship
* @param string|Title of the drodpwon field
* @param FieldList or Array | Options listed in the dropdown
* @param Current|object has_one object, if exists
* @param object|The object calling this field, required by HasOneButtonField
*/
class HasOneSelectOrCreateField extends CompositeField
{
protected DropdownField $dropdown;

protected $dropdown;

protected $gridfield;
protected HasOneButtonField $gridfield;

public function __construct($record, $name, $title, $options, $current, $parent)
{
Expand All @@ -49,21 +48,20 @@ public function __construct($record, $name, $title, $options, $current, $parent)
if ($current && $current->exists()) {
$name = ($current->Title) ? $current->Title : $current->Name;
if ($name) {
$button->setButtonName('Edit '.FormField::name_to_label($name));
$button->setButtonName('Edit ' . FormField::name_to_label($name));
}
} else {
$button->setButtonName('Create '.$label);
$button->setButtonName('Create ' . $label);
}

// Set Empty String on dropdown
$dropdown->setEmptyString('Select '.$label);
$dropdown->setEmptyString('Select ' . $label);

parent::__construct(array($this->dropdown, $this->gridfield));
parent::__construct([$this->dropdown, $this->gridfield]);
}

public function getRelationName()
public function getRelationName(): string
{
return $this->name.'ID';
return $this->name . 'ID';
}

}
Loading