absences_AgentRightMovementFrame   A
last analyzed

Complexity

Total Complexity 4

Size/Duplication

Total Lines 52
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 10

Importance

Changes 0
Metric Value
wmc 4
lcom 0
cbo 10
dl 0
loc 52
rs 10
c 0
b 0
f 0

2 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 23 2
A addMovement() 0 22 2
1
<?php
2
/************************************************************************
3
 * OVIDENTIA http://www.ovidentia.org                                   *
4
 ************************************************************************
5
 * Copyright (c) 2003 by CANTICO ( http://www.cantico.fr )              *
6
 *                                                                      *
7
 * This file is part of Ovidentia.                                      *
8
 *                                                                      *
9
 * Ovidentia is free software; you can redistribute it and/or modify    *
10
 * it under the terms of the GNU General Public License as published by *
11
 * the Free Software Foundation; either version 2, or (at your option)  *
12
 * any later version.													*
13
 *																		*
14
 * This program is distributed in the hope that it will be useful, but  *
15
 * WITHOUT ANY WARRANTY; without even the implied warranty of			*
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.					*
17
 * See the  GNU General Public License for more details.				*
18
 *																		*
19
 * You should have received a copy of the GNU General Public License	*
20
 * along with this program; if not, write to the Free Software			*
21
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,*
22
 * USA.																	*
23
************************************************************************/
24
25
require_once dirname(__FILE__).'/right.ui.php';
26
27
28
bab_Widgets()->includePhpClass('Widget_Form');
29
30
31
32
class absences_AgentRightEditor extends absences_RightBaseEditor 
33
{
34
	/**
35
	 * 
36
	 * @var absences_AgentRight
37
	 */
38
	protected $agentRight;
39
	
40
41
	/**
42
	 * @var Widget_RadioSet
43
	 */
44
	protected $quantity_type;
45
	
46
	
47
	public function __construct(absences_AgentRight $agentright)
48
	{
49
		$W = bab_Widgets();
50
		
51
		parent::__construct(null, $W->VBoxLayout()->setVerticalSpacing(1,'em'));
52
		
53
		$this->agentRight = $agentright;
54
		
55
		bab_functionality::includefile('Icons');
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class bab_functionality as the method includefile() does only exist in the following sub-classes of bab_functionality: Func_Archive, Func_Archive_Zip, Func_Archive_Zip_ZipArchive, Func_Archive_Zip_Zlib, Func_CalendarBackend, Func_CalendarBackend_Ovi, Func_ContextActions, Func_ContextActions_Article, Func_ContextActions_ArticleTopic, Func_Home, Func_Home_Ovidentia, Func_Icons, Func_Icons_Default, Func_Ovml, Func_Ovml_Container, Func_Ovml_Container_Addon, Func_Ovml_Container_Article, Func_Ovml_Container_ArticleCategories, Func_Ovml_Container_ArticleCategory, Func_Ovml_Container_ArticleCategoryNext, Func_Ovml_Container_ArticleCategoryPrevious, Func_Ovml_Container_ArticleFiles, Func_Ovml_Container_ArticleNext, Func_Ovml_Container_ArticlePrevious, Func_Ovml_Container_ArticleTopic, Func_Ovml_Container_ArticleTopicNext, Func_Ovml_Container_ArticleTopicPrevious, Func_Ovml_Container_ArticleTopics, Func_Ovml_Container_Articles, Func_Ovml_Container_ArticlesHomePages, Func_Ovml_Container_CalendarCategories, Func_Ovml_Container_CalendarEventDomains, Func_Ovml_Container_CalendarEvents, Func_Ovml_Container_CalendarGroupEvents, Func_Ovml_Container_CalendarResourceEvents, Func_Ovml_Container_CalendarUserEvents, Func_Ovml_Container_Calendars, Func_Ovml_Container_DbDirectories, Func_Ovml_Container_DbDirectory, Func_Ovml_Container_DbDirectoryAcl, Func_Ovml_Container_DbDirectoryEntry, Func_Ovml_Container_DbDirectoryEntryFields, Func_Ovml_Container_DbDirectoryFields, Func_Ovml_Container_DbDirectoryMemberFields, Func_Ovml_Container_DbDirectoryMembers, Func_Ovml_Container_Delegation, Func_Ovml_Container_DelegationAdministrators, Func_Ovml_Container_DelegationItems, Func_Ovml_Container_DelegationManaged, Func_Ovml_Container_Delegations, Func_Ovml_Container_DelegationsCategories, Func_Ovml_Container_DelegationsCategory, Func_Ovml_Container_DelegationsManaged, Func_Ovml_Container_Faq, Func_Ovml_Container_FaqNext, Func_Ovml_Container_FaqPrevious, Func_Ovml_Container_FaqQuestion, Func_Ovml_Container_FaqQuestionNext, Func_Ovml_Container_FaqQuestionPrevious, Func_Ovml_Container_FaqQuestions, Func_Ovml_Container_FaqSubCategories, Func_Ovml_Container_FaqSubCategory, Func_Ovml_Container_Faqs, Func_Ovml_Container_File, Func_Ovml_Container_FileFields, Func_Ovml_Container_FileNext, Func_Ovml_Container_FilePrevious, Func_Ovml_Container_Files, Func_Ovml_Container_Folder, Func_Ovml_Container_FolderNext, Func_Ovml_Container_FolderPrevious, Func_Ovml_Container_Folders, Func_Ovml_Container_Forum, Func_Ovml_Container_ForumNext, Func_Ovml_Container_ForumPrevious, Func_Ovml_Container_Forums, Func_Ovml_Container_IfEqual, Func_Ovml_Container_IfGreaterThan, Func_Ovml_Container_IfGreaterThanOrEqual, Func_Ovml_Container_IfIsSet, Func_Ovml_Container_IfLessThan, Func_Ovml_Container_IfLessThanOrEqual, Func_Ovml_Container_IfNotEqual, Func_Ovml_Container_IfNotIsSet, Func_Ovml_Container_IfUserMemberOfGroups, Func_Ovml_Container_Multipages, Func_Ovml_Container_ObjectsInfo, Func_Ovml_Container_OrgPathToEntity, Func_Ovml_Container_OrgUserEntities, Func_Ovml_Container_OvmlArray, Func_Ovml_Container_OvmlArrayFields, Func_Ovml_Container_OvmlSoap, Func_Ovml_Container_ParentsArticleCategory, Func_Ovml_Container_Post, Func_Ovml_Container_PostFiles, Func_Ovml_Container_RecentArticles, Func_Ovml_Container_RecentComments, Func_Ovml_Container_RecentFaqQuestions, Func_Ovml_Container_RecentFiles, Func_Ovml_Container_RecentPosts, Func_Ovml_Container_RecentThreads, Func_Ovml_Container_SitemapCustomNode, Func_Ovml_Container_SitemapEntries, Func_Ovml_Container_SitemapEntry, Func_Ovml_Container_SitemapPath, Func_Ovml_Container_Soap, Func_Ovml_Container_SubFolders, Func_Ovml_Container_Tags, Func_Ovml_Container_Thread, Func_Ovml_Container_TmProjects, Func_Ovml_Container_TmSpaces, Func_Ovml_Container_TmTaskFields, Func_Ovml_Container_TmTasks, Func_Ovml_Container_WaitingArticles, Func_Ovml_Container_WaitingComments, Func_Ovml_Container_WaitingFiles, Func_Ovml_Container_WaitingPosts, Func_Ovml_Function, Func_Ovml_Function_AOAddition, Func_Ovml_Function_AODivision, Func_Ovml_Function_AOModulus, Func_Ovml_Function_AOMultiplication, Func_Ovml_Function_AOSubtraction, Func_Ovml_Function_AddStyleSheet, Func_Ovml_Function_Addon, Func_Ovml_Function_Ajax, Func_Ovml_Function_ArticleTree, Func_Ovml_Function_CurrentNode, Func_Ovml_Function_FileTree, Func_Ovml_Function_Get, Func_Ovml_Function_GetCookie, Func_Ovml_Function_GetCsrfProtectToken, Func_Ovml_Function_GetCurrentAdmGroup, Func_Ovml_Function_GetLanguage, Func_Ovml_Function_GetPageTitle, Func_Ovml_Function_GetPath, Func_Ovml_Function_GetSelectedSkinPath, Func_Ovml_Function_GetSessionVar, Func_Ovml_Function_GetVar, Func_Ovml_Function_Header, Func_Ovml_Function_IfNotIsSet, Func_Ovml_Function_Include, Func_Ovml_Function_NextArticle, Func_Ovml_Function_Post, Func_Ovml_Function_PreviousArticle, Func_Ovml_Function_PreviousOrNextArticle, Func_Ovml_Function_PutArray, Func_Ovml_Function_PutSoapArray, Func_Ovml_Function_PutVar, Func_Ovml_Function_Recurse, Func_Ovml_Function_Request, Func_Ovml_Function_SetCookie, Func_Ovml_Function_SetSessionVar, Func_Ovml_Function_SitemapCustomNodeId, Func_Ovml_Function_SitemapMenu, Func_Ovml_Function_SitemapPosition, Func_Ovml_Function_SitemapUrl, Func_Ovml_Function_Translate, Func_Ovml_Function_UrlContent, Func_Ovml_Function_WebStat, Func_PortalAuthentication, Func_PortalAuthentication_AuthOvidentia, Func_PwdComplexity, Func_PwdComplexity_DefaultPortal, Func_SearchUi, Func_SitemapDynamicNode, Func_SitemapDynamicNode_Topic, Func_UserEditor, Func_WorkingHours, Func_WorkingHours_Ovidentia, Ovml_Container_Sitemap, bab_ArithmeticOperator, bab_Ovml_Container_Operator, bab_rgp. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
56
		
57
		$this->setName('agent_right');
58
		$this->addClass('widget-bordered');
59
		$this->addClass('BabLoginMenuBackground');
60
		$this->addClass('widget-centered');
61
		$this->addClass(Func_Icons::ICON_LEFT_24);
62
		$this->colon();
63
		
64
		$this->setCanvasOptions($this->Options()->width(70,'em'));
0 ignored issues
show
Bug introduced by
It seems like $this->Options()->width(70, 'em') targeting Widget_CanvasOptions::width() can also be of type double; however, Widget_Item::setCanvasOptions() does only seem to accept object<Widget_CanvasOptions>, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
65
		
66
		$this->addFields();
67
		$this->loadFormValues();
68
		
69
		$this->addButtons();
70
		$this->setSelfPageHiddenFields();
71
	}
72
	
73
	
74
	protected function addFields()
75
	{
76
		$this 
77
			->addItem($this->quantity_type())
78
			->addItem($this->quantity())
79
			->addItem($this->availability_rules())
80
			->addItem($this->renewal())
81
		;
82
		
83
		
84
		
85
		$right = $this->agentRight->getRight();
86
		$rightCet = $right->getRightCet();
87
		if ($rightCet->getRow())
88
		{
89
			$this->addItem($this->saving());
90
		}
91
		
92
		$this->addItem($this->movement_comment());
93
	}
94
	
95
	
96
	/**
97
	 * 
98
	 */
99 View Code Duplication
	protected function movement_comment()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
100
	{
101
		$W = bab_Widgets();
102
		
103
		return $W->LabelledWidget(
104
			absences_translate('Comment on modification for history'), 
105
			$W->TextEdit()->setLines(2)->setMandatory(true, absences_translate('The comment is mandatory'))->addClass('widget-fullwidth'), 
106
			__FUNCTION__
107
		);
108
	}
109
	
110
	
111
	
112
	
113
	protected function loadFormValues()
114
	{
115
		
116
		$this->setHiddenValue('agent_right[id]', $this->agentRight->id);
117
		
118
		if (isset($_POST['agent_right']))
119
		{
120
			$values = $_POST['agent_right'];
121
		} else if (isset($this->agentRight))
122
		{
123
			$values = $this->agentRight->getRow();
124
			$right = $this->agentRight->getRight();
125
			$values['quantity'] = absences_editQuantity($this->agentRight->getQuantity(), $right->quantity_unit);
126
127
			$values['quantity_type'] = 'right';
128
			
129
			if ('' !== (string) $this->agentRight->quantity) {
130
			    $values['quantity_type'] = 'agent';
131
			}
132
			
133
134
		} else {
135
			return;
136
		}
137
138
		
139
		$this->setValues(array('agent_right' => $values));
140
	}
141
	
142
	
143 View Code Duplication
	protected function addButtons()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
144
	{
145
		$W = bab_Widgets();
146
		
147
		$button = $W->FlowItems(
148
			$W->SubmitButton()->setName('cancel')->setLabel(absences_translate('Cancel')),
149
			$W->SubmitButton()->setName('save')->setLabel(absences_translate('Save'))
150
		)->setSpacing(1,'em');
151
		
152
		$this->addItem($button);
153
	}
154
	
155
	
156
	/**
157
	 * Criteres de disponibilite d'un droit
158
	 */
159
	protected function availability_rules()
160
	{
161
		$W = bab_Widgets();
162
	
163
	
164
	
165
		$input_date = $this->by_request_input_date();
166
		
167
		$accordions = $W->Accordions()
168
			->addPanel(absences_translate('Availability depends on the date of the vacation request input'), $input_date)
169
			->addPanel(absences_translate('Availability depends on the requested period dates'), $this->by_requested_period())
170
		;
171
		
172
		// $accordions->setOpenPanel($input_date->getId());
173
		
174
		return $accordions;
175
	}
176
	
177
	
178
	
179
	/**
180
	 * Availability depends on the requested period dates
181
	 */
182
	protected function by_requested_period()
183
	{
184
		$W = bab_Widgets();
185
		$period = $W->PeriodPicker()->setNames('inperiod_start', 'inperiod_end');
186
		
187
		$validoverlap = $W->LabelledWidget(
188
				absences_translate('Allow overlap between the request period and the test periods'),
189
				$W->CheckBox(),
190
				'validoverlap'
191
		);
192
	
193
		return $W->VBoxItems(
194
				$W->Label(absences_translate('The right is available if the vacation request is in the period')),
195
				$period,
196
				$validoverlap
197
		)->setVerticalSpacing(1,'em');
198
	}
199
	
200
	
201
	
202
	protected function getSign($value)
203
	{
204
	    if ($value >= 0) {
205
	        return '+';
206
	    }
207
	    
208
	    return '-';
209
	}
210
	
211
	
212
	protected function quantity_type()
213
	{
214
	    $W = bab_Widgets();
215
	    
216
	    $right = $this->agentRight->getRight();
217
	    $q = absences_quantity($right->quantity, $right->quantity_unit);
218
	    $nb = 1;
219
	    
220 View Code Duplication
	    if ($increment = $right->getIncrementQuantity()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
221
	        if (0 !== (int) round(100 * $increment)) {
222
	            $q .= sprintf(absences_translate(' %s %s by monthly update'), $this->getSign($increment), absences_quantity(abs($increment), $right->quantity_unit));
223
	            $nb++;
224
	        }
225
	    }
226
	    
227 View Code Duplication
	    if ($dynamic = $this->agentRight->getDynamicQuantity()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
228
	        if (0 !== (int) round(100 * $dynamic)) {
229
	            $q .= sprintf(absences_translate(' %s %s by consumption'), $this->getSign($increment), absences_quantity(abs($dynamic), $right->quantity_unit));
230
	            $nb++;
231
	        }
232
	    }
233
	    
234
	    if ($nb > 1) {
235
	        $q .= ' = '.absences_quantity($this->agentRight->getRightQuantity(), $right->quantity_unit);
236
	    }
237
	    
238
	    
239
	    $this->quantity_type = $W->RadioSet()
240
	       ->setName('quantity_type')
241
	       ->addOption('right', sprintf(absences_translate('Use the quantity provided by the right (%s)'), $q))
242
	       ->addOption('agent', absences_translate('Use a specific value'));
243
	    
244
	    return $this->quantity_type;
245
	}
246
	
247
	
248
	
249
	/**
250
	 * quantity
251
	 * quantite initiale + les ajustement dynamiques du droits (variables par mois + droits dynamiques)
252
	 * 
253
	 * @return Widget_FlowLayout
254
	 */
255
	protected function quantity()
256
	{
257
		$W = bab_Widgets();
258
	
259
		$lineedit = $W->LineEdit()->setSize(4)->setMaxSize(5)->setName('quantity');
260
		
261
		
262
		$right = $this->agentRight->getRight();
263
		$q = array();
264
		
265
		$increment = $this->agentRight->getAgentIncrementQuantity();
266
		if ($increment || $right->getIncrementQuantity()) {
267
		    $q[] = sprintf(absences_translate('%s by monthly update'), absences_quantity($increment, $right->quantity_unit));
268
		}
269
		 
270
		if ($dynamic = $this->agentRight->getDynamicQuantity()) {
271
		    if (0 !== (int) round(100 * $dynamic)) {
272
		        $q[] = sprintf(absences_translate('%s by consumption'), absences_quantity($dynamic, $right->quantity_unit));
273
		    }
274
		}
275
		
276
		$description = null;
277
		if ($q) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $q of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
278
		    $description = sprintf(absences_translate('The input quantity include %s'), implode(', ', $q));
279
		}
280
		
281
		
282
		$quantity = $W->LabelledWidget(
283
		    absences_translate('Quantity available for the user'),
284
		    $lineedit,
285
		    'quantity',
286
		    $description,
287
		    $this->agentRight->getRight()->getUnitLabel()
288
	    );
289
		
290
		
291
		$this->quantity_type->setAssociatedDisplayable($quantity, array('agent'));
292
		
293
		return $quantity;
294
	}
295
	
296
	
297
	
298
	protected function renewal()
299
	{
300
	    $W = bab_Widgets();
301
	    
302
	    return $W->LabelledWidget(absences_translate('Include this right in the next yearly renewal'), $W->CheckBox(), __FUNCTION__);
303
	}
304
	
305
}	
306
307
308
309
310
311
class absences_QuantityModificationCardFrame extends absences_CardFrame
312
{
313
    protected function createTable()
314
    {
315
        $W = bab_Widgets();
316
        bab_functionality::includeOriginal('Icons');
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class bab_functionality as the method includeOriginal() does only exist in the following sub-classes of bab_functionality: Func_Archive, Func_Archive_Zip, Func_Archive_Zip_ZipArchive, Func_Archive_Zip_Zlib, Func_CalendarBackend, Func_CalendarBackend_Ovi, Func_ContextActions, Func_ContextActions_Article, Func_ContextActions_ArticleTopic, Func_Home, Func_Home_Ovidentia, Func_Icons, Func_Icons_Default, Func_Ovml, Func_Ovml_Container, Func_Ovml_Container_Addon, Func_Ovml_Container_Article, Func_Ovml_Container_ArticleCategories, Func_Ovml_Container_ArticleCategory, Func_Ovml_Container_ArticleCategoryNext, Func_Ovml_Container_ArticleCategoryPrevious, Func_Ovml_Container_ArticleFiles, Func_Ovml_Container_ArticleNext, Func_Ovml_Container_ArticlePrevious, Func_Ovml_Container_ArticleTopic, Func_Ovml_Container_ArticleTopicNext, Func_Ovml_Container_ArticleTopicPrevious, Func_Ovml_Container_ArticleTopics, Func_Ovml_Container_Articles, Func_Ovml_Container_ArticlesHomePages, Func_Ovml_Container_CalendarCategories, Func_Ovml_Container_CalendarEventDomains, Func_Ovml_Container_CalendarEvents, Func_Ovml_Container_CalendarGroupEvents, Func_Ovml_Container_CalendarResourceEvents, Func_Ovml_Container_CalendarUserEvents, Func_Ovml_Container_Calendars, Func_Ovml_Container_DbDirectories, Func_Ovml_Container_DbDirectory, Func_Ovml_Container_DbDirectoryAcl, Func_Ovml_Container_DbDirectoryEntry, Func_Ovml_Container_DbDirectoryEntryFields, Func_Ovml_Container_DbDirectoryFields, Func_Ovml_Container_DbDirectoryMemberFields, Func_Ovml_Container_DbDirectoryMembers, Func_Ovml_Container_Delegation, Func_Ovml_Container_DelegationAdministrators, Func_Ovml_Container_DelegationItems, Func_Ovml_Container_DelegationManaged, Func_Ovml_Container_Delegations, Func_Ovml_Container_DelegationsCategories, Func_Ovml_Container_DelegationsCategory, Func_Ovml_Container_DelegationsManaged, Func_Ovml_Container_Faq, Func_Ovml_Container_FaqNext, Func_Ovml_Container_FaqPrevious, Func_Ovml_Container_FaqQuestion, Func_Ovml_Container_FaqQuestionNext, Func_Ovml_Container_FaqQuestionPrevious, Func_Ovml_Container_FaqQuestions, Func_Ovml_Container_FaqSubCategories, Func_Ovml_Container_FaqSubCategory, Func_Ovml_Container_Faqs, Func_Ovml_Container_File, Func_Ovml_Container_FileFields, Func_Ovml_Container_FileNext, Func_Ovml_Container_FilePrevious, Func_Ovml_Container_Files, Func_Ovml_Container_Folder, Func_Ovml_Container_FolderNext, Func_Ovml_Container_FolderPrevious, Func_Ovml_Container_Folders, Func_Ovml_Container_Forum, Func_Ovml_Container_ForumNext, Func_Ovml_Container_ForumPrevious, Func_Ovml_Container_Forums, Func_Ovml_Container_IfEqual, Func_Ovml_Container_IfGreaterThan, Func_Ovml_Container_IfGreaterThanOrEqual, Func_Ovml_Container_IfIsSet, Func_Ovml_Container_IfLessThan, Func_Ovml_Container_IfLessThanOrEqual, Func_Ovml_Container_IfNotEqual, Func_Ovml_Container_IfNotIsSet, Func_Ovml_Container_IfUserMemberOfGroups, Func_Ovml_Container_Multipages, Func_Ovml_Container_ObjectsInfo, Func_Ovml_Container_OrgPathToEntity, Func_Ovml_Container_OrgUserEntities, Func_Ovml_Container_OvmlArray, Func_Ovml_Container_OvmlArrayFields, Func_Ovml_Container_OvmlSoap, Func_Ovml_Container_ParentsArticleCategory, Func_Ovml_Container_Post, Func_Ovml_Container_PostFiles, Func_Ovml_Container_RecentArticles, Func_Ovml_Container_RecentComments, Func_Ovml_Container_RecentFaqQuestions, Func_Ovml_Container_RecentFiles, Func_Ovml_Container_RecentPosts, Func_Ovml_Container_RecentThreads, Func_Ovml_Container_SitemapCustomNode, Func_Ovml_Container_SitemapEntries, Func_Ovml_Container_SitemapEntry, Func_Ovml_Container_SitemapPath, Func_Ovml_Container_Soap, Func_Ovml_Container_SubFolders, Func_Ovml_Container_Tags, Func_Ovml_Container_Thread, Func_Ovml_Container_TmProjects, Func_Ovml_Container_TmSpaces, Func_Ovml_Container_TmTaskFields, Func_Ovml_Container_TmTasks, Func_Ovml_Container_WaitingArticles, Func_Ovml_Container_WaitingComments, Func_Ovml_Container_WaitingFiles, Func_Ovml_Container_WaitingPosts, Func_Ovml_Function, Func_Ovml_Function_AOAddition, Func_Ovml_Function_AODivision, Func_Ovml_Function_AOModulus, Func_Ovml_Function_AOMultiplication, Func_Ovml_Function_AOSubtraction, Func_Ovml_Function_AddStyleSheet, Func_Ovml_Function_Addon, Func_Ovml_Function_Ajax, Func_Ovml_Function_ArticleTree, Func_Ovml_Function_CurrentNode, Func_Ovml_Function_FileTree, Func_Ovml_Function_Get, Func_Ovml_Function_GetCookie, Func_Ovml_Function_GetCsrfProtectToken, Func_Ovml_Function_GetCurrentAdmGroup, Func_Ovml_Function_GetLanguage, Func_Ovml_Function_GetPageTitle, Func_Ovml_Function_GetPath, Func_Ovml_Function_GetSelectedSkinPath, Func_Ovml_Function_GetSessionVar, Func_Ovml_Function_GetVar, Func_Ovml_Function_Header, Func_Ovml_Function_IfNotIsSet, Func_Ovml_Function_Include, Func_Ovml_Function_NextArticle, Func_Ovml_Function_Post, Func_Ovml_Function_PreviousArticle, Func_Ovml_Function_PreviousOrNextArticle, Func_Ovml_Function_PutArray, Func_Ovml_Function_PutSoapArray, Func_Ovml_Function_PutVar, Func_Ovml_Function_Recurse, Func_Ovml_Function_Request, Func_Ovml_Function_SetCookie, Func_Ovml_Function_SetSessionVar, Func_Ovml_Function_SitemapCustomNodeId, Func_Ovml_Function_SitemapMenu, Func_Ovml_Function_SitemapPosition, Func_Ovml_Function_SitemapUrl, Func_Ovml_Function_Translate, Func_Ovml_Function_UrlContent, Func_Ovml_Function_WebStat, Func_PortalAuthentication, Func_PortalAuthentication_AuthOvidentia, Func_PwdComplexity, Func_PwdComplexity_DefaultPortal, Func_SearchUi, Func_SitemapDynamicNode, Func_SitemapDynamicNode_Topic, Func_UserEditor, Func_WorkingHours, Func_WorkingHours_Ovidentia, Ovml_Container_Sitemap, bab_ArithmeticOperator, bab_Ovml_Container_Operator, bab_rgp. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
317
        
318
        $table = $W->BabTableView();
319
        $table->addClass('absences-quantity-modification-table');
320
        $table->addClass(Func_Icons::ICON_LEFT_16);
321
        
322
        $table->addColumnClass(0, 'date');
323
        
324
        return $table;
325
    }
326
    
327
    
328
    protected function quantityLabel($quantity, $unit)
329
    {
330
        $W = bab_Widgets();
331
        
332
        $sign = '+';
333
        if ($quantity < 0) {
334
            $sign = '-';
335
        }
336
        
337
        return $W->Label($sign.absences_quantity(abs($quantity), $unit));
338
    }
339
}
340
341
342
343
344
345
346
347
348
class absences_IncrementCardFrame extends absences_QuantityModificationCardFrame
349
{
350
    protected $agentright;
351
352
    public $contain_rows = false;
353
354 View Code Duplication
    public function __construct(absences_AgentRight $agentright, $layout = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
355
    {
356
        parent::__construct(null, $layout);
357
358
        $this->agentright = $agentright;
359
360
361
        $this->addClass('absences-dynamicright-cardframe');
362
        $this->addClass(Func_Icons::ICON_LEFT_16);
363
364
        $this->loadPage();
365
    }
366
367
368
369
    protected function loadPage()
370
    {
371
        require_once $GLOBALS['babInstallPath'].'utilit/urlincl.php';
372
        $W = bab_Widgets();
373
374
375
        $this->addItem($W->Title(absences_translate('Quantity modifications by monthly right modification')));
376
377
        
378
        $addon = bab_getAddonInfosInstance('absences');
0 ignored issues
show
Unused Code introduced by
$addon is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
379
        $right = $this->agentright->getRight();
380
        $table = $this->createTable();
381
382
        $row = 0;
383
        
384
        $table->addItem($W->Label(absences_translate('Initial quantity'))->addClass('right')->colon(), $row, 0);
385
        $table->addItem($W->Label(absences_quantity($this->agentright->getInitialQuantity(), $right->quantity_unit)), $row, 1);
386
        $row++;
387
        
388
        
389
        $table->addHeadRow($row);
390
391
        $table->addItem($W->Label(absences_translate('Modification date')), $row, 0);
392
        $table->addItem($W->Label(absences_translate('Quantity added to the right')), $row, 1);
393
        $row++;
394
395
        $I = $this->agentright->getIncrementIterator();
396
397
        if ($I->count() > 0)
0 ignored issues
show
Bug introduced by
The method count cannot be called on $I (of type array<integer,object<absences_IncrementRecord>>).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
398
        {
399
            $this->contain_rows = true;
400
        }
401
        
402
        
403
        if ($I instanceof absences_IncrementAgentRightIterator) {
404
            $this->addItem($W->Icon(
405
                absences_translate('The montly update are added each month from the specific user quantity because the user quantity has been modified. To get back to the default value, the quantity field must be set empty'),
406
                Func_Icons::STATUS_DIALOG_INFORMATION
407
            ));
408
        }
409
        
410
        if ($I instanceof absences_IncrementRightIterator) {
411
            $this->addItem($W->Icon(
412
                absences_translate('The montly update are added each month from the right quantity, if a specific quantity is set for the user, such changes will no longer be used'),
413
                Func_Icons::STATUS_DIALOG_INFORMATION
414
            ));
415
        }
416
        
417
418
        
419
420
        foreach($I as $increment)
421
        {
422
            $table->addItem($W->Label(bab_shortDate(bab_mktime($increment->createdOn))), $row, 0);
423
            $table->addItem($this->quantityLabel($increment->quantity, $right->quantity_unit), $row, 1);
424
            	
425
            $row++;
426
        }
427
428
429
        
430
431
        $this->addItem($table);
432
    }
433
}
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
class absences_DynamicRightCardFrame extends absences_QuantityModificationCardFrame
451
{
452
	protected $agentright;
453
	
454
	public $contain_rows = false;
455
	
456 View Code Duplication
	public function __construct(absences_AgentRight $agentright, $layout = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
457
	{
458
		parent::__construct(null, $layout);
459
	
460
		$this->agentright = $agentright;
461
462
		
463
		$this->addClass('absences-dynamicright-cardframe');
464
		$this->addClass(Func_Icons::ICON_LEFT_16);
465
	
466
		$this->loadPage();
467
	}
468
	
469
	
470
	
471
	protected function loadPage()
472
	{
473
	    require_once $GLOBALS['babInstallPath'].'utilit/urlincl.php';
474
		$W = bab_Widgets();
475
		bab_functionality::includeOriginal('Icons');
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class bab_functionality as the method includeOriginal() does only exist in the following sub-classes of bab_functionality: Func_Archive, Func_Archive_Zip, Func_Archive_Zip_ZipArchive, Func_Archive_Zip_Zlib, Func_CalendarBackend, Func_CalendarBackend_Ovi, Func_ContextActions, Func_ContextActions_Article, Func_ContextActions_ArticleTopic, Func_Home, Func_Home_Ovidentia, Func_Icons, Func_Icons_Default, Func_Ovml, Func_Ovml_Container, Func_Ovml_Container_Addon, Func_Ovml_Container_Article, Func_Ovml_Container_ArticleCategories, Func_Ovml_Container_ArticleCategory, Func_Ovml_Container_ArticleCategoryNext, Func_Ovml_Container_ArticleCategoryPrevious, Func_Ovml_Container_ArticleFiles, Func_Ovml_Container_ArticleNext, Func_Ovml_Container_ArticlePrevious, Func_Ovml_Container_ArticleTopic, Func_Ovml_Container_ArticleTopicNext, Func_Ovml_Container_ArticleTopicPrevious, Func_Ovml_Container_ArticleTopics, Func_Ovml_Container_Articles, Func_Ovml_Container_ArticlesHomePages, Func_Ovml_Container_CalendarCategories, Func_Ovml_Container_CalendarEventDomains, Func_Ovml_Container_CalendarEvents, Func_Ovml_Container_CalendarGroupEvents, Func_Ovml_Container_CalendarResourceEvents, Func_Ovml_Container_CalendarUserEvents, Func_Ovml_Container_Calendars, Func_Ovml_Container_DbDirectories, Func_Ovml_Container_DbDirectory, Func_Ovml_Container_DbDirectoryAcl, Func_Ovml_Container_DbDirectoryEntry, Func_Ovml_Container_DbDirectoryEntryFields, Func_Ovml_Container_DbDirectoryFields, Func_Ovml_Container_DbDirectoryMemberFields, Func_Ovml_Container_DbDirectoryMembers, Func_Ovml_Container_Delegation, Func_Ovml_Container_DelegationAdministrators, Func_Ovml_Container_DelegationItems, Func_Ovml_Container_DelegationManaged, Func_Ovml_Container_Delegations, Func_Ovml_Container_DelegationsCategories, Func_Ovml_Container_DelegationsCategory, Func_Ovml_Container_DelegationsManaged, Func_Ovml_Container_Faq, Func_Ovml_Container_FaqNext, Func_Ovml_Container_FaqPrevious, Func_Ovml_Container_FaqQuestion, Func_Ovml_Container_FaqQuestionNext, Func_Ovml_Container_FaqQuestionPrevious, Func_Ovml_Container_FaqQuestions, Func_Ovml_Container_FaqSubCategories, Func_Ovml_Container_FaqSubCategory, Func_Ovml_Container_Faqs, Func_Ovml_Container_File, Func_Ovml_Container_FileFields, Func_Ovml_Container_FileNext, Func_Ovml_Container_FilePrevious, Func_Ovml_Container_Files, Func_Ovml_Container_Folder, Func_Ovml_Container_FolderNext, Func_Ovml_Container_FolderPrevious, Func_Ovml_Container_Folders, Func_Ovml_Container_Forum, Func_Ovml_Container_ForumNext, Func_Ovml_Container_ForumPrevious, Func_Ovml_Container_Forums, Func_Ovml_Container_IfEqual, Func_Ovml_Container_IfGreaterThan, Func_Ovml_Container_IfGreaterThanOrEqual, Func_Ovml_Container_IfIsSet, Func_Ovml_Container_IfLessThan, Func_Ovml_Container_IfLessThanOrEqual, Func_Ovml_Container_IfNotEqual, Func_Ovml_Container_IfNotIsSet, Func_Ovml_Container_IfUserMemberOfGroups, Func_Ovml_Container_Multipages, Func_Ovml_Container_ObjectsInfo, Func_Ovml_Container_OrgPathToEntity, Func_Ovml_Container_OrgUserEntities, Func_Ovml_Container_OvmlArray, Func_Ovml_Container_OvmlArrayFields, Func_Ovml_Container_OvmlSoap, Func_Ovml_Container_ParentsArticleCategory, Func_Ovml_Container_Post, Func_Ovml_Container_PostFiles, Func_Ovml_Container_RecentArticles, Func_Ovml_Container_RecentComments, Func_Ovml_Container_RecentFaqQuestions, Func_Ovml_Container_RecentFiles, Func_Ovml_Container_RecentPosts, Func_Ovml_Container_RecentThreads, Func_Ovml_Container_SitemapCustomNode, Func_Ovml_Container_SitemapEntries, Func_Ovml_Container_SitemapEntry, Func_Ovml_Container_SitemapPath, Func_Ovml_Container_Soap, Func_Ovml_Container_SubFolders, Func_Ovml_Container_Tags, Func_Ovml_Container_Thread, Func_Ovml_Container_TmProjects, Func_Ovml_Container_TmSpaces, Func_Ovml_Container_TmTaskFields, Func_Ovml_Container_TmTasks, Func_Ovml_Container_WaitingArticles, Func_Ovml_Container_WaitingComments, Func_Ovml_Container_WaitingFiles, Func_Ovml_Container_WaitingPosts, Func_Ovml_Function, Func_Ovml_Function_AOAddition, Func_Ovml_Function_AODivision, Func_Ovml_Function_AOModulus, Func_Ovml_Function_AOMultiplication, Func_Ovml_Function_AOSubtraction, Func_Ovml_Function_AddStyleSheet, Func_Ovml_Function_Addon, Func_Ovml_Function_Ajax, Func_Ovml_Function_ArticleTree, Func_Ovml_Function_CurrentNode, Func_Ovml_Function_FileTree, Func_Ovml_Function_Get, Func_Ovml_Function_GetCookie, Func_Ovml_Function_GetCsrfProtectToken, Func_Ovml_Function_GetCurrentAdmGroup, Func_Ovml_Function_GetLanguage, Func_Ovml_Function_GetPageTitle, Func_Ovml_Function_GetPath, Func_Ovml_Function_GetSelectedSkinPath, Func_Ovml_Function_GetSessionVar, Func_Ovml_Function_GetVar, Func_Ovml_Function_Header, Func_Ovml_Function_IfNotIsSet, Func_Ovml_Function_Include, Func_Ovml_Function_NextArticle, Func_Ovml_Function_Post, Func_Ovml_Function_PreviousArticle, Func_Ovml_Function_PreviousOrNextArticle, Func_Ovml_Function_PutArray, Func_Ovml_Function_PutSoapArray, Func_Ovml_Function_PutVar, Func_Ovml_Function_Recurse, Func_Ovml_Function_Request, Func_Ovml_Function_SetCookie, Func_Ovml_Function_SetSessionVar, Func_Ovml_Function_SitemapCustomNodeId, Func_Ovml_Function_SitemapMenu, Func_Ovml_Function_SitemapPosition, Func_Ovml_Function_SitemapUrl, Func_Ovml_Function_Translate, Func_Ovml_Function_UrlContent, Func_Ovml_Function_WebStat, Func_PortalAuthentication, Func_PortalAuthentication_AuthOvidentia, Func_PwdComplexity, Func_PwdComplexity_DefaultPortal, Func_SearchUi, Func_SitemapDynamicNode, Func_SitemapDynamicNode_Topic, Func_UserEditor, Func_WorkingHours, Func_WorkingHours_Ovidentia, Ovml_Container_Sitemap, bab_ArithmeticOperator, bab_Ovml_Container_Operator, bab_rgp. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
476
		
477
		
478
		$this->addItem($W->Title(absences_translate('Quantity modifications depending on the consumed quantity')));
479
		
480
		$right = $this->agentright->getRight();
481
		$t = $right->getDynamicTypes();
482
		
483
		$this->addItem($W->Label(sprintf(absences_translate('%s has consumed %s of %s beetween the %s and the %s'), 
484
				$this->agentright->getAgent()->getName(),
485
				absences_quantity(round($this->agentright->getDynamicTotalConfirmedDays(), 2), 'D'),
486
				implode(', ', $t),
487
				bab_shortDate(bab_mktime($right->dynconf_begin), false),
488
				bab_shortDate(bab_mktime($right->dynconf_end), false)
489
		)));
490
		
491
		
492
		$table = $this->createTable();
493
		
494
495
        $row = 0;
496
        
497
        $increment_quantity = $this->agentright->getIncrementQuantity();
498
        $initial_title = 0 === (int) round(100*$increment_quantity) ? absences_translate('Initial quantity') : absences_translate('Initial quantity + monthly updates');
499
        $table->addItem($W->Label($initial_title)->addClass('right')->colon(), $row, 0);
500
        $initial = $this->agentright->getInitialQuantity();
501
        $initial += $increment_quantity;
502
        $table->addItem($W->Label(absences_quantity($initial, $right->quantity_unit)), $row, 1, 1, 2);
503
        $row++;
504
        
505
        
506
        $table->addHeadRow($row);
507
		
508
		$table->addItem($W->Label(absences_translate('Modification date')), $row, 0);
509
		$table->addItem($W->Label(absences_translate('Quantity added to the right')), $row, 1);
510
		$table->addItem($W->Label(absences_translate('Vacation request that caused the change')), $row, 2);
511
		$row++;
512
		
513
		$right = $this->agentright->getRight();
514
		
515
		$I = $this->agentright->getDynamicRightIterator();
516
		
517
		if ($I->count() > 0)
518
		{
519
			$this->contain_rows = true;
520
		}
521
		
522
		$addon = bab_getAddonInfosInstance('absences');
523
		
524
		foreach($I as $dynamicRight)
525
		{
526
			/* @var $dynamicRight absences_DynamicRight */
527
		    
528
		    $request_url = new bab_url($addon->getUrl().'vacadmb');
529
		    $request_url->idx = 'morvw';
530
		    $request_url->id = $dynamicRight->id_entry;
531
		    $request_url->popup = 1;
532
			
533
			$table->addItem($W->Label(bab_shortDate(bab_mktime($dynamicRight->createdOn))), $row, 0);
534
			$table->addItem($this->quantityLabel($dynamicRight->quantity, $right->quantity_unit), $row, 1);
535
			$table->addItem($W->Link($W->Icon('', Func_Icons::ACTIONS_DOCUMENT_PROPERTIES), $request_url->toString())->setOpenMode(Widget_Link::OPEN_POPUP), $row, 2);
536
			
537
			$row++;
538
		}
539
		
540
		
541
		$this->addItem($table);
542
	}
543
}
544
545
546
547
548
549
class absences_AgentRightMovementFrame extends absences_CardFrame
550
{
551
    public $count;
552
    
553
    public function __construct(absences_AgentRight $agentRight)
554
    {
555
        $W = bab_Widgets();
556
        parent::__construct(null, $W->VBoxLayout()->setVerticalSpacing(.5, 'em'));
557
        
558
        
559
        
560
        $this->addClass('widget-bordered');
561
        $this->addClass('widget-centered');
562
        $this->addClass(Func_Icons::ICON_LEFT_24);
563
        
564
        $this->setCanvasOptions($this->Options()->width(70,'em'));
0 ignored issues
show
Bug introduced by
It seems like $this->Options()->width(70, 'em') targeting Widget_CanvasOptions::width() can also be of type double; however, Widget_Item::setCanvasOptions() does only seem to accept object<Widget_CanvasOptions>, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
565
        
566
        $this->addItem($W->Title(absences_translate('History')));
567
        
568
        $res = $agentRight->getMovementIterator();
569
        $this->count = $res->count();
570
        
571
        foreach ($res as $movement) {
572
            
573
            $this->addMovement($movement);
574
        }
575
    }
576
    
577
    
578
    protected function addMovement(absences_Movement $movement)
579
    {
580
        $W = bab_Widgets();
581
        
582
        $date = $W->Label(bab_shortDate(bab_mktime($movement->createdOn)));
583
        $message = $W->RichText($movement->message)->setRenderingOptions(BAB_HTML_ALL ^ BAB_HTML_P);
584
        
585
        $date->setTitle(bab_getUserName($movement->id_author));
586
        
587
        if ($movement->comment) {
588
            $message = $W->VBoxItems(
589
                $message,
590
                $W->FlowItems(
591
                    $W->Label(absences_translate('Comment'))->colon(),
592
                    $W->RichText($movement->comment)->setRenderingOptions(BAB_HTML_ALL ^ BAB_HTML_P)
593
                )->setSpacing(.8, 'em')
594
            )->setSpacing(.5, 'em');
595
        }
596
        
597
        
598
        $this->addItem($W->HBoxItems($date, $message));
599
    }
600
}