Completed
Push — master ( f99fed...57dceb )
by Jean-Christophe
03:29
created

HtmlTR::addValues()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
3
namespace Ajax\semantic\html\content\table;
4
5
use Ajax\semantic\html\base\HtmlSemCollection;
6
use Ajax\semantic\html\base\constants\State;
7
use Ajax\semantic\html\base\traits\TableElementTrait;
8
use Ajax\service\JArray;
9
10
/**
11
 *
12
 * @author jc
13
 *
14
 */
15
class HtmlTR extends HtmlSemCollection {
16
	use TableElementTrait;
17
	private $_tdTagName;
18
	private $_container;
19
	private $_row;
20
21
	public function __construct($identifier) {
22
		parent::__construct($identifier, "tr", "");
23
		$this->_states=[ State::ACTIVE,State::POSITIVE,State::NEGATIVE,State::WARNING,State::ERROR,State::DISABLED ];
24
	}
25
26
	public function setColCount($colCount) {
27
		$count=$this->count();
28
		for($i=$count; $i < $colCount; $i++) {
29
			$item=$this->addItem(NULL);
30
			$item->setTagName($this->_tdTagName);
31
		}
32
		return $this;
33
	}
34
35
	/**
36
	 *
37
	 * {@inheritDoc}
38
	 *
39
	 * @see \Ajax\common\html\HtmlCollection::createItem()
40
	 */
41
	protected function createItem($value) {
42
		$count=$this->count();
43
		$td=new HtmlTD("", $value, $this->_tdTagName);
44
		$td->setContainer($this->_container, $this->_row, $count);
45
		return $td;
46
	}
47
48
	public function setTdTagName($tagName="td") {
49
		$this->_tdTagName=$tagName;
50
	}
51
52
	/**
53
	 * Define the container (HtmlTableContent) and the num of the row
54
	 * @param HtmlTableContent $container
55
	 * @param int $row
56
	 */
57
	public function setContainer($container, $row) {
58
		$this->_container=$container;
59
		$this->_row=$row;
60
	}
61
62
	/**
63
	 * Sets values to the row cols
64
	 * @param mixed $values
65
	 */
66
	public function setValues($values=array()) {
67
		return $this->_addOrSetValues($values, function(&$cell,$value){$cell->setValue($value);});
68
	}
69
70
	/**
71
	 * Adds values to the row cols
72
	 * @param mixed $values
73
	 */
74
	public function addValues($values=array()) {
75
		return $this->_addOrSetValues($values, function(&$cell,$value){$cell->addValue($value);});
76
	}
77
78
	/**
79
	 * Sets or adds values to the row cols
80
	 * @param mixed $values
81
	 */
82
	protected function _addOrSetValues($values,$callback) {
83
		$count=$this->count();
84
		if (!\is_array($values)) {
85
			$values=\array_fill(0, $count, $values);
86
		} else {
87
			if (JArray::isAssociative($values) === true) {
88
				$values=\array_values($values);
89
			}
90
		}
91
		$count=\min(\sizeof($values), $count);
92
93 View Code Duplication
		for($i=0; $i < $count; $i++) {
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...
94
			$cell=$this->content[$i];
95
			$callback($cell,$values[$i]);
96
		}
97
		return $this;
98
	}
99
100
	/**
101
	 * Removes the col at $index
102
	 * @param int $index the index of the col to remove
103
	 * @return \Ajax\semantic\html\content\table\HtmlTR
104
	 */
105
	public function delete($index) {
106
		$this->removeItem($index);
107
		return $this;
108
	}
109
110
	public function mergeCol($colIndex=0) {
111
		return $this->getItem($colIndex)->mergeCol();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Ajax\common\html\HtmlDoubleElement as the method mergeCol() does only exist in the following sub-classes of Ajax\common\html\HtmlDoubleElement: Ajax\semantic\html\content\table\HtmlTD, Ajax\semantic\html\content\table\HtmlTR, Ajax\semantic\html\content\table\HtmlTableContent. 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...
112
	}
113
114
	public function mergeRow($colIndex=0) {
115
		return $this->getItem($colIndex)->mergeRow();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Ajax\common\html\HtmlDoubleElement as the method mergeRow() does only exist in the following sub-classes of Ajax\common\html\HtmlDoubleElement: Ajax\semantic\html\content\table\HtmlTD, Ajax\semantic\html\content\table\HtmlTR, Ajax\semantic\html\content\table\HtmlTableContent. 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...
116
	}
117
118
	public function getColPosition($colIndex) {
119
		$pos=0;
120
		$rows=$this->_container->getContent();
121
		for($i=0; $i < $this->_row; $i++) {
122
			$max=\min($colIndex, $rows[$i]->count());
123
			for($j=0; $j < $max; $j++) {
124
				$rowspan=$rows[$i]->getItem($j)->getRowspan();
125
				if ($rowspan + $i > $this->_row)
126
					$pos++;
127
			}
128
		}
129
		if ($pos > $colIndex)
130
			return NULL;
131
		$count=$this->count();
132
		for($i=0; $i < $count; $i++) {
133
			$pos+=$this->content[$i]->getColspan();
134
			if ($pos >= $colIndex + 1)
135
				return $i;
136
		}
137
		return null;
138
	}
139
140
	public function conditionalCellFormat($callback, $format) {
141
		$cells=$this->content;
142
		foreach ( $cells as $cell ) {
143
			$cell->conditionalCellFormat($callback, $format);
144
		}
145
		return $this;
146
	}
147
148
	public function conditionalRowFormat($callback, $format) {
149
		if ($callback($this)) {
150
			$this->addToProperty("class", $format);
151
		}
152
		return $this;
153
	}
154
155
	public function containsStr($needle) {
156
		$cells=$this->content;
157
		foreach ( $cells as $cell ) {
158
			if (\strpos($cell->getContent(), $needle) !== false)
159
				return true;
160
		}
161
		return false;
162
	}
163
164
	public function apply($callback) {
165
		$callback($this);
166
		return $this;
167
	}
168
169
	public function applyCells($callback) {
170
		$cells=$this->content;
171
		foreach ( $cells as $cell ) {
172
			$cell->apply($callback);
173
		}
174
		return $this;
175
	}
176
}