Open DIDoS opened 6 years ago
Why do you want to put this in the template file? I think this kind of logic is fairly "edge-case" and to implement this level of conditional logic into the library is a bit hectic and will add to maintenance complexity.
Doing this yourself in the current code is quite easy:
Guests:
${MORE_THAN_3_GUESTS_BLOCK}
Don't forget to make a special arrangement for more than 3 guests!
${/MORE_THAN_3_GUESTS_BLOCK}
PHP
if(count($guests) > 3) {
$templateProcessor->cloneBlock('MORE_THAN_3_GUESTS_BLOCK', 1);
} else {
$templateProcessor->deleteBlock('MORE_THAN_3_GUESTS_BLOCK');
}
Not sure how many cases you have where you'd need this kind of conditional logic, but I'm pretty sure it will be easier to manage the code in your controller than trying to implement it into the library and your templates.
I support this request. We create different PHP Sources for documents and create different documents out of one source. So it's easier to create conditions in the template and not in php code.
I support this request. We create different PHP Sources for documents and create different documents out of one source. So it's easier to create conditions in the template and not in php code.
I agree with @rkorebrits ,and @gruessung can fit your requirement with this way: set a rule like "greater_books3", they are separated by "", the first part means "condition", it can be some values such as "greater", "equals". Second part means your variable, in this case, it means "books", third part means numbers, and that you can code your php with this rule
@icy2003 @rkorebrits Ofc I am fully aware how this can be done in the code rather than in the template (as mentioned in my original PR "...rather than in the code."). The reason why this makes sense is the same reason templating languages exist at all: separation of concerns. You want to get your data together in the code and feed it to a template that executes the "presentation" logic. This way it's easier to debug, maintain and it's separated in modules by function. It also enforces a good programming practice by keeping business logic away from presentation logic.
Better
Guests:
${IF GUESTS>3}
Don't forget to make a special arrangement for more than 3 guests!
${/ENDIF}
or
Guests:
{IF $GUESTS>3}
Don't forget to make a special arrangement for more than 3 guests!
{/ENDIF}
To avoid mixing variables and functions.
Better
Guests: ${IF GUESTS>3} Don't forget to make a special arrangement for more than 3 guests! ${/ENDIF}
or
Guests: {IF $GUESTS>3} Don't forget to make a special arrangement for more than 3 guests! {/ENDIF}
To avoid mixing variables and functions.
is this the next version function?
Better
Guests: ${IF GUESTS>3} Don't forget to make a special arrangement for more than 3 guests! ${/ENDIF}
or
Guests: {IF $GUESTS>3} Don't forget to make a special arrangement for more than 3 guests! {/ENDIF}
To avoid mixing variables and functions.
I don't see the difference in the first one? Did you mean the first "or" the second one or the second one instead of the first one. The reason why I did it that way was because of the way the Template Processor is written right now. Every macro must start with a Dollar sign. The additional logic would be quiet easy to add with a whitelist of key word (functions such as IF) and a check of operands for this function (as regex for example). Also an open/close sanity check (e.g. IF/ENDIF) would have to be added.
Any other issues someone sees with this feature?
Why do you want to put this in the template file? I think this kind of logic is fairly "edge-case" and to implement this level of conditional logic into the library is a bit hectic and will add to maintenance complexity.
Doing this yourself in the current code is quite easy:
Guests: ${MORE_THAN_3_GUESTS_BLOCK} Don't forget to make a special arrangement for more than 3 guests! ${/MORE_THAN_3_GUESTS_BLOCK}
PHP
if(count($guests) > 3) { $templateProcessor->cloneBlock('MORE_THAN_3_GUESTS_BLOCK', 1); } else { $templateProcessor->deleteBlock('MORE_THAN_3_GUESTS_BLOCK'); }
Not sure how many cases you have where you'd need this kind of conditional logic, but I'm pretty sure it will be easier to manage the code in your controller than trying to implement it into the library and your templates.
This doesn't seem to work within a numbered list.
@DIDoS any update on implementing this feature?
@troosan any idea how I could make your suggestion work with numbered lists?
Any news on this? Would really solve a lot of hassle in multiple implementations. Python's docx templating lib supports Jinja2 - which also provides in-template-logic handling, so would be good to see it here in PhpWord
Is any update on this issue?
Any update? 😀 Maybe I should just start implementing myself I guess...
Hello Community,
@vpiskunov Thanks for your suggestion of using python-docx-template. It sure looks promising for handling the in-template logic.
I was wondering if we have any update on this request though?
I believe the following reasons are worth considering for developing this feature. 1) This will surely reduce the reliance on developers to get every change pushed to the market. 2) Any person businessperson with a basic understanding of templating logic can make changes in the text and/or conditions. 3) If the template document is revising frequently, handling template logic in code will require frequent releases 4) As pointed by @AidanHak, the suggested alternative implementation does not handle numbered_list.
I moved over to OpenTBS around the time I first noticed this issue. Works like a charm for my needs.
My template has boolean variables, this variables can be "Yes" or "No" for using in template. Additional I want add dynamic text by boolean variables
I solve this problem with small function:
private function handleConditions(TemplateProcessor $templateProcessor, array &$variables, ?int $index = null): void
{
$conditions = array_filter($templateProcessor->getVariables(), fn($variable) => Str::startsWith($variable, 'IF('));
foreach ($conditions as $condition) {
$rule = Str::between($condition, 'IF(', ')'); // Str its Laravel's Facade
[$variable, $trueValue, $falseValue] = explode(';', $rule);
$variableName = $index ? $variable . "#$index" : $variable;
if (isset($variables[$variableName])) {
$variables[$condition] = $variables[$variableName] === 'Yes' ? $trueValue : $falseValue;
}
}
}
in template I have row "IF(VARIABLE;True text;else text)"
Example of use:
$variables = [
'Name' => $this->name,
'Checked' => $this->isChecked ? 'Yes' : 'No',
];
$this->handleConditions($templateProcessor, $variables);
$templateProcessor->setValues($variables);
And example for cloned blocks:
$templateProcessor->cloneBlock(
'Step',
$this->count(),
true,
true,
);
foreach ($steps as $index => $step) {
$index++;
$stepVariables = [
'StepName' => $step->name,
'IsChecked' => $step->isChecked ? 'Yes' : 'No',
];
$this->handleConditions($templateProcessor, $stepVariables, $index);
$templateProcessor->setValues($stepVariables);
}
I also require this functionality. Using the setValue method to assign an empty value doesn't eliminate the element; rather, it merely empties the text, leaving a line in the document, which is less than ideal. removeBlock does not work in nested block. no choice but to implement:
Create a new class that extends TemplateProcessor and incorporated a new method called removeValue.
public function removeValue($blockname)
{
$xml = simplexml_load_string($this->tempDocumentMainPart);
$paragraphs = $xml->xpath('//w:p');
foreach ($paragraphs as $paragraph)
{
// Check if paragraph and text node exist
$t = (string)$paragraph->asXML();
if (strpos($t, $blockname) !== false) {
// Convert SimpleXML to DOMDocument
$dom = dom_import_simplexml($paragraph);
$dom->parentNode->removeChild($dom);
break;
}
}
$this->tempDocumentMainPart = $xml->asXML();
}
hope it helps!
This is:
Expected Behavior
Being able to put conditions in a template block rather than in the code. Current macros only support replacement and repeats (clone, replace, set).
I want to start a discussion about this before I might implement it and send a PR.
I guess it would look something like that:
In the docx "template":
In the code:
This could be extended by several operands (<, >, <=, >=, !=, ==) or even nested logical expressions.
Pro: More transparent templates (view logic where it belongs)
Con: More complexity in template processor