Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Y
yii2
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
PSDI Army
yii2
Commits
688870c1
Commit
688870c1
authored
Jul 16, 2011
by
Qiang Xue
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
finished Dictionary.
parent
83068e0d
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
193 additions
and
176 deletions
+193
-176
Dictionary.php
framework/base/Dictionary.php
+146
-142
DictionaryIterator.php
framework/base/DictionaryIterator.php
+22
-24
Vector.php
framework/base/Vector.php
+25
-10
No files found.
framework/base/Dictionary.php
View file @
688870c1
<?php
namespace
yii\base
;
/**
*
This file contains classes implementing Map featur
e.
*
Dictionary class fil
e.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright Copyright © 2008-201
1
Yii Software LLC
* @copyright Copyright © 2008-201
2
Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace
yii\base
;
/**
*
CMap implements a collection that tak
es key-value pairs.
*
Dictionary implements a collection that stor
es key-value pairs.
*
* You can access, add or remove an item with a key by using
* {@link itemAt}, {@link add}, and {@link remove}.
* To get the number of the items in the map, use {@link getCount}.
* CMap can also be used like a regular array as follows,
* <pre>
* $map[$key]=$value; // add a key-value pair
* unset($map[$key]); // remove the value with the specified key
* if(isset($map[$key])) // if the map contains the key
* foreach($map as $key=>$value) // traverse the items in the map
* $n=count($map); // returns the number of items in the map
* </pre>
* [[itemAt]], [[add]], and [[remove]].
*
* To get the number of the items in the dictionary, use [[getCount]].
*
* Because Dictionary implements a set of SPL interfaces, it can be used
* like a regular PHP array as follows,
*
* ~~~php
* $dictionary[$key] = $value; // add a key-value pair
* unset($dictionary[$key]); // remove the value with the specified key
* if (isset($dictionary[$key])) // if the dictionary contains the key
* foreach ($dictionary as $key=>$value) // traverse the items in the dictionary
* $n = count($dictionary); // returns the number of items in the dictionary
* ~~~
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @version $Id: CMap.php 3153 2011-04-01 12:50:06Z qiang.xue $
* @package system.collections
* @since 1.0
* @since 2.0
*/
class
Dictionary
extends
Component
implements
\IteratorAggregate
,
\ArrayAccess
,
\Countable
{
/**
* @var array internal data storage
* @var boolean whether this vector is read-only or not.
* If the vector is read-only, adding or moving items will throw an exception.
*/
p
rivate
$_d
=
array
()
;
p
ublic
$readOnly
;
/**
* @var
boolean whether this list is read-only
* @var
array internal data storage
*/
private
$_
r
=
false
;
private
$_
d
=
array
()
;
/**
* Constructor.
* Initializes the list with an array or an iterable object.
* @param array $data the intial data. Default is null, meaning no initialization.
* @param boolean $readOnly whether the list is read-only
* @throws CException If data is not null and neither an array nor an iterator.
* Initializes the dictionary with an array or an iterable object.
* @param mixed $data the initial data to be populated into the dictionary.
* This can be an array or an iterable object.
* @param boolean $readOnly whether the dictionary is read-only
* @throws Exception if data is not well formed (neither an array nor an iterable object)
*/
public
function
__construct
(
$data
=
null
,
$readOnly
=
false
)
public
function
__construct
(
$data
=
array
(),
$readOnly
=
false
)
{
if
(
$data
!==
null
)
if
(
$data
!==
array
())
{
$this
->
copyFrom
(
$data
);
$this
->
setReadOnly
(
$readOnly
);
}
/**
* @return boolean whether this map is read-only or not. Defaults to false.
*/
public
function
getReadOnly
()
{
return
$this
->
_r
;
}
/**
* @param boolean $value whether this list is read-only or not
*/
protected
function
setReadOnly
(
$value
)
{
$this
->
_r
=
$value
;
}
$this
->
readOnly
=
$readOnly
;
}
/**
* Returns an iterator for traversing the items in the list.
* This method is required by the interface IteratorAggregate.
* @return CMapIterator an iterator for traversing the items in the list.
* Returns an iterator for traversing the items in the dictionary.
* This method is required by the SPL interface `IteratorAggregate`.
* It will be implicitly called when you use `foreach` to traverse the dictionary.
* @return DictionaryIterator an iterator for traversing the items in the dictionary.
*/
public
function
getIterator
()
{
return
new
CMap
Iterator
(
$this
->
_d
);
return
new
Dictionary
Iterator
(
$this
->
_d
);
}
/**
* Returns the number of items in the map.
* This method is required by Countable interface.
* @return integer number of items in the map.
* Returns the number of items in the dictionary.
* This method is required by the SPL `Countable` interface.
* It will be implicitly called when you use `count($dictionary)`.
* @return integer number of items in the dictionary.
*/
public
function
count
()
{
...
...
@@ -93,8 +83,8 @@ class Dictionary extends Component implements \IteratorAggregate, \ArrayAccess,
}
/**
* Returns the number of items in the
map
.
* @return integer the number of items in the
map
* Returns the number of items in the
dictionary
.
* @return integer the number of items in the
dictionary
*/
public
function
getCount
()
{
...
...
@@ -102,6 +92,7 @@ class Dictionary extends Component implements \IteratorAggregate, \ArrayAccess,
}
/**
* Returns the keys stored in the dictionary.
* @return array the key list
*/
public
function
getKeys
()
...
...
@@ -111,84 +102,83 @@ class Dictionary extends Component implements \IteratorAggregate, \ArrayAccess,
/**
* Returns the item with the specified key.
* This method is exactly the same as {@link offsetGet}.
* @param mixed $key the key
* @return mixed the element at the offset, null if no element is found at the offset
* @return mixed the element with the specified key.
* Null if the key cannot be found in the dictionary.
*/
public
function
itemAt
(
$key
)
{
if
(
isset
(
$this
->
_d
[
$key
]))
return
$this
->
_d
[
$key
];
else
return
null
;
return
isset
(
$this
->
_d
[
$key
])
?
$this
->
_d
[
$key
]
:
null
;
}
/**
* Adds an item into the
map
.
* Adds an item into the
dictionary
.
* Note, if the specified key already exists, the old value will be overwritten.
* @param mixed $key key
* @param mixed $value value
* @throws
CException if the map
is read-only
* @throws
Exception if the dictionary
is read-only
*/
public
function
add
(
$key
,
$value
)
public
function
add
(
$key
,
$value
)
{
if
(
!
$this
->
_r
)
{
if
(
$key
===
null
)
$this
->
_d
[]
=
$value
;
else
$this
->
_d
[
$key
]
=
$value
;
if
(
!
$this
->
readOnly
)
{
if
(
$key
===
null
)
{
$this
->
_d
[]
=
$value
;
}
else
{
$this
->
_d
[
$key
]
=
$value
;
}
}
else
{
throw
new
Exception
(
'Dictionary is read only.'
);
}
else
throw
new
CException
(
Yii
::
t
(
'yii'
,
'The map is read only.'
));
}
/**
* Removes an item from the
map
by its key.
* Removes an item from the
dictionary
by its key.
* @param mixed $key the key of the item to be removed
* @return mixed the removed value, null if no such key exists.
* @throws
CException if the map
is read-only
* @throws
Exception if the dictionary
is read-only
*/
public
function
remove
(
$key
)
{
if
(
!
$this
->
_r
)
{
if
(
isset
(
$this
->
_d
[
$key
]))
{
$value
=
$this
->
_d
[
$key
];
if
(
!
$this
->
readOnly
)
{
if
(
isset
(
$this
->
_d
[
$key
]))
{
$value
=
$this
->
_d
[
$key
];
unset
(
$this
->
_d
[
$key
]);
return
$value
;
}
else
{
// it is possible the value is null, which is not detected by isset
else
{
// the value is null
unset
(
$this
->
_d
[
$key
]);
return
null
;
}
}
else
throw
new
CException
(
Yii
::
t
(
'yii'
,
'The map is read only.'
));
else
{
throw
new
Exception
(
'Dictionary is read only.'
);
}
}
/**
* Removes all items in the
map
.
* Removes all items in the
dictionary
.
*/
public
function
clear
()
{
foreach
(
array_keys
(
$this
->
_d
)
as
$key
)
foreach
(
array_keys
(
$this
->
_d
)
as
$key
)
{
$this
->
remove
(
$key
);
}
}
/**
* Returns a value indicating whether the dictionary contains the specified key.
* @param mixed $key the key
* @return boolean whether the
map
contains an item with the specified key
* @return boolean whether the
dictionary
contains an item with the specified key
*/
public
function
contains
(
$key
)
{
return
isset
(
$this
->
_d
[
$key
])
||
array_key_exists
(
$key
,
$this
->
_d
);
return
isset
(
$this
->
_d
[
$key
])
||
array_key_exists
(
$key
,
$this
->
_d
);
}
/**
* Returns the dictionary as a PHP array.
* @return array the list of items in array
*/
public
function
toArray
()
...
...
@@ -197,33 +187,37 @@ class Dictionary extends Component implements \IteratorAggregate, \ArrayAccess,
}
/**
* Copies iterable data into the
map
.
* Note, existing data in the
map
will be cleared first.
* @param mixed $data the data to be copied from, must be an array or
object implementing Traversable
* @throws
CException I
f data is neither an array nor an iterator.
* Copies iterable data into the
dictionary
.
* Note, existing data in the
dictionary
will be cleared first.
* @param mixed $data the data to be copied from, must be an array or
an object implementing `Traversable`
* @throws
Exception i
f data is neither an array nor an iterator.
*/
public
function
copyFrom
(
$data
)
{
if
(
is_array
(
$data
)
||
$data
instanceof
Traversable
)
if
(
is_array
(
$data
)
||
$data
instanceof
Traversable
)
{
if
(
$this
->
getCount
()
>
0
)
if
((
$this
->
_d
!==
array
())
{
$this
->
clear
();
if
(
$data
instanceof
CMap
)
$data
=
$data
->
_d
;
foreach
(
$data
as
$key
=>
$value
)
$this
->
add
(
$key
,
$value
);
}
if
(
$data
instanceof
self
)
{
$data
=
$data
->
_d
;
}
foreach
(
$data
as
$key
=>
$value
)
{
$this
->
add
(
$key
,
$value
);
}
}
else
{
throw
new
Exception
(
'Data must be either an array or an object implementing Traversable.'
);
}
else
if
(
$data
!==
null
)
throw
new
CException
(
Yii
::
t
(
'yii'
,
'Map data must be an array or an object implementing Traversable.'
));
}
/**
* Merges iterable data into the
map
.
* Merges iterable data into the
dictionary
.
*
* Existing elements in the
map
will be overwritten if their keys are the same as those in the source.
* Existing elements in the
dictionary
will be overwritten if their keys are the same as those in the source.
* If the merge is recursive, the following algorithm is performed:
* <ul>
* <li>the
map
data is saved as $a, and the source data is saved as $b;</li>
* <li>the
dictionary
data is saved as $a, and the source data is saved as $b;</li>
* <li>if $a and $b both have an array indxed at the same string key, the arrays will be merged using this algorithm;</li>
* <li>any integer-indexed elements in $b will be appended to $a and reindxed accordingly;</li>
* <li>any string-indexed elements in $b will overwrite elements in $a with the same index;</li>
...
...
@@ -236,13 +230,13 @@ class Dictionary extends Component implements \IteratorAggregate, \ArrayAccess,
*/
public
function
mergeWith
(
$data
,
$recursive
=
true
)
{
if
(
is_array
(
$data
)
||
$data
instanceof
Traversable
)
if
(
is_array
(
$data
)
||
$data
instanceof
Traversable
)
{
if
(
$data
instanceof
CMap
)
if
(
$data
instanceof
Dictionary
)
$data
=
$data
->
_d
;
if
(
$recursive
)
if
(
$recursive
)
{
if
(
$data
instanceof
Traversable
)
if
(
$data
instanceof
Traversable
)
{
$d
=
array
();
foreach
(
$data
as
$key
=>
$value
)
...
...
@@ -258,40 +252,15 @@ class Dictionary extends Component implements \IteratorAggregate, \ArrayAccess,
$this
->
add
(
$key
,
$value
);
}
}
else
if
(
$data
!==
null
)
throw
new
CException
(
Yii
::
t
(
'yii'
,
'Map data must be an array or an object implementing Traversable.'
));
}
/**
* Merges two arrays into one recursively.
* If each array has an element with the same string key value, the latter
* will overwrite the former (different from array_merge_recursive).
* Recursive merging will be conducted if both arrays have an element of array
* type and are having the same key.
* For integer-keyed elements, the elements from the latter array will
* be appended to the former array.
* @param array $a array to be merged to
* @param array $b array to be merged from
* @return array the merged array (the original arrays are not changed.)
* @see mergeWith
*/
public
static
function
mergeArray
(
$a
,
$b
)
{
foreach
(
$b
as
$k
=>
$v
)
{
if
(
is_integer
(
$k
))
isset
(
$a
[
$k
])
?
$a
[]
=
$v
:
$a
[
$k
]
=
$v
;
else
if
(
is_array
(
$v
)
&&
isset
(
$a
[
$k
])
&&
is_array
(
$a
[
$k
]))
$a
[
$k
]
=
self
::
mergeArray
(
$a
[
$k
],
$v
);
else
$a
[
$k
]
=
$v
;
}
return
$a
;
else
if
(
$data
!==
null
)
throw
new
CException
(
Yii
::
t
(
'yii'
,
'Dictionary data must be an array or an object implementing Traversable.'
));
}
/**
* Returns whether there is an element at the specified offset.
* This method is required by the interface ArrayAccess.
* This method is required by the SPL interface `ArrayAccess`.
* It is implicitly called when you use something like `isset($vector[$index])`.
* This is equivalent to [[contains]].
* @param mixed $offset the offset to check on
* @return boolean
*/
...
...
@@ -302,7 +271,9 @@ class Dictionary extends Component implements \IteratorAggregate, \ArrayAccess,
/**
* Returns the element at the specified offset.
* This method is required by the interface ArrayAccess.
* This method is required by the SPL interface `ArrayAccess`.
* It is implicitly called when you use something like `$value = $dictionary[$index];`.
* This is equivalent to [[itemAt]].
* @param integer $offset the offset to retrieve element.
* @return mixed the element at the offset, null if no element is found at the offset
*/
...
...
@@ -313,22 +284,55 @@ class Dictionary extends Component implements \IteratorAggregate, \ArrayAccess,
/**
* Sets the element at the specified offset.
* This method is required by the interface ArrayAccess.
* @param integer $offset the offset to set element
* This method is required by the SPL interface `ArrayAccess`.
* It is implicitly called when you use something like `$dictionary[$key] = $value;`.
* If the offset is null, the new item will be appended to the dictionary.
* Otherwise, the existing item at the offset will be replaced with the new item.
* This is equivalent to [[add]].
* @param mixed $offset the offset to set element
* @param mixed $item the element value
*/
public
function
offsetSet
(
$offset
,
$item
)
public
function
offsetSet
(
$offset
,
$item
)
{
$this
->
add
(
$offset
,
$item
);
}
/**
* Unsets the element at the specified offset.
* This method is required by the interface ArrayAccess.
* This method is required by the SPL interface `ArrayAccess`.
* It is implicitly called when you use something like `unset($dictionary[$index])`.
* This is equivalent to [[remove]].
* @param mixed $offset the offset to unset element
*/
public
function
offsetUnset
(
$offset
)
{
$this
->
remove
(
$offset
);
}
/**
* Merges two arrays into one recursively.
* If each array has an element with the same string key value, the latter
* will overwrite the former (different from array_merge_recursive).
* Recursive merging will be conducted if both arrays have an element of array
* type and are having the same key.
* For integer-keyed elements, the elements from the latter array will
* be appended to the former array.
* @param array $a array to be merged to
* @param array $b array to be merged from
* @return array the merged array (the original arrays are not changed.)
* @see mergeWith
*/
public
static
function
mergeArray
(
$a
,
$b
)
{
foreach
(
$b
as
$k
=>
$v
)
{
if
(
is_integer
(
$k
))
isset
(
$a
[
$k
])
?
$a
[]
=
$v
:
$a
[
$k
]
=
$v
;
else
if
(
is_array
(
$v
)
&&
isset
(
$a
[
$k
])
&&
is_array
(
$a
[
$k
]))
$a
[
$k
]
=
self
::
mergeArray
(
$a
[
$k
],
$v
);
else
$a
[
$k
]
=
$v
;
}
return
$a
;
}
}
framework/base/DictionaryIterator.php
View file @
688870c1
<?php
namespace
yii\base
;
/**
*
CMap
Iterator class file.
*
Dictionary
Iterator class file.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright Copyright © 2008-201
1
Yii Software LLC
* @copyright Copyright © 2008-201
2
Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace
yii\base
;
/**
*
CMapIterator implements an interator for {@link CMap}
.
*
DictionaryIterator implements the SPL `Iterator` interface for [[Dictionary]]
.
*
* It allows CMap to return a new iterator for traversing the items in the map.
* It allows [[Dictionary]] to return a new iterator for data traversing purpose.
* You normally do not use this class directly.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @version $Id: CMapIterator.php 3186 2011-04-15 22:34:55Z alexander.makarow $
* @package system.collections
* @since 1.0
* @since 2.0
*/
class
DictionaryIterator
implements
\Iterator
{
...
...
@@ -42,23 +40,23 @@ class DictionaryIterator implements \Iterator
*/
public
function
__construct
(
&
$data
)
{
$this
->
_d
=
&
$data
;
$this
->
_keys
=
array_keys
(
$data
);
$this
->
_key
=
reset
(
$this
->
_keys
);
$this
->
_d
=
&
$data
;
$this
->
_keys
=
array_keys
(
$data
);
$this
->
_key
=
reset
(
$this
->
_keys
);
}
/**
* Rewinds
internal array pointer
.
* This method is required by the
interface Iterator
.
* Rewinds
the index of the current item
.
* This method is required by the
SPL interface `Iterator`
.
*/
public
function
rewind
()
{
$this
->
_key
=
reset
(
$this
->
_keys
);
$this
->
_key
=
reset
(
$this
->
_keys
);
}
/**
* Returns the key of the current array element.
* This method is required by the
interface Iterator
.
* This method is required by the
SPL interface `Iterator`
.
* @return mixed the key of the current array element
*/
public
function
key
()
...
...
@@ -68,7 +66,7 @@ class DictionaryIterator implements \Iterator
/**
* Returns the current array element.
* This method is required by the
interface Iterator
.
* This method is required by the
SPL interface `Iterator`
.
* @return mixed the current array element
*/
public
function
current
()
...
...
@@ -77,21 +75,21 @@ class DictionaryIterator implements \Iterator
}
/**
* Moves the internal pointer to the next
array
element.
* This method is required by the
interface Iterator
.
* Moves the internal pointer to the next element.
* This method is required by the
SPL interface `Iterator`
.
*/
public
function
next
()
{
$this
->
_key
=
next
(
$this
->
_keys
);
$this
->
_key
=
next
(
$this
->
_keys
);
}
/**
* Returns whether there is an element at current position.
* This method is required by the
interface Iterator
.
* @return boolean
* This method is required by the
SPL interface `Iterator`
.
* @return boolean
whether there is an item at current position.
*/
public
function
valid
()
{
return
$this
->
_key
!==
false
;
return
$this
->
_key
!==
false
;
}
}
framework/base/Vector.php
View file @
688870c1
...
...
@@ -58,7 +58,7 @@ class Vector extends Component implements \IteratorAggregate, \ArrayAccess, \Cou
* Constructor.
* Initializes the vector with an array or an iterable object.
* @param mixed $data the initial data to be populated into the vector.
* This can be an array or an iterable object.
If null, the vector will be set as empty.
* This can be an array or an iterable object.
* @param boolean $readOnly whether the vector should be marked as read-only.
* @throws Exception if data is not well formed (neither an array nor an iterable object)
*/
...
...
@@ -115,8 +115,9 @@ class Vector extends Component implements \IteratorAggregate, \ArrayAccess, \Cou
elseif
(
$index
>=
0
&&
$index
<
$this
->
_c
)
{
// in case the value is null
return
$this
->
_d
[
$index
];
}
throw
new
Exception
(
'Index out of range: '
.
$index
);
else
{
throw
new
Exception
(
'Index out of range: '
.
$index
);
}
}
/**
...
...
@@ -149,9 +150,13 @@ class Vector extends Component implements \IteratorAggregate, \ArrayAccess, \Cou
array_splice
(
$this
->
_d
,
$index
,
0
,
array
(
$item
));
$this
->
_c
++
;
}
throw
new
Exception
(
'Index out of range: '
.
$index
);
else
{
throw
new
Exception
(
'Index out of range: '
.
$index
);
}
}
else
{
throw
new
Exception
(
'Vector is read only.'
);
}
throw
new
Exception
(
'Vector is read only.'
);
}
/**
...
...
@@ -170,8 +175,9 @@ class Vector extends Component implements \IteratorAggregate, \ArrayAccess, \Cou
$this
->
removeAt
(
$index
);
return
$index
;
}
else
else
{
return
false
;
}
}
/**
...
...
@@ -194,9 +200,13 @@ class Vector extends Component implements \IteratorAggregate, \ArrayAccess, \Cou
return
$item
;
}
}
throw
new
Exception
(
'Index out of range: '
.
$index
);
else
{
throw
new
Exception
(
'Index out of range: '
.
$index
);
}
}
else
{
throw
new
Exception
(
'Vector is read only.'
);
}
throw
new
Exception
(
'Vector is read only.'
);
}
/**
...
...
@@ -261,7 +271,9 @@ class Vector extends Component implements \IteratorAggregate, \ArrayAccess, \Cou
$this
->
add
(
$item
);
}
}
throw
new
Exception
(
'Data must be either an array or an object implementing Traversable.'
);
else
{
throw
new
Exception
(
'Data must be either an array or an object implementing Traversable.'
);
}
}
/**
...
...
@@ -280,7 +292,9 @@ class Vector extends Component implements \IteratorAggregate, \ArrayAccess, \Cou
$this
->
add
(
$item
);
}
}
throw
new
Exception
(
'Data must be either an array or an object implementing Traversable.'
);
else
{
throw
new
Exception
(
'Data must be either an array or an object implementing Traversable.'
);
}
}
/**
...
...
@@ -299,6 +313,7 @@ class Vector extends Component implements \IteratorAggregate, \ArrayAccess, \Cou
* Returns the item at the specified offset.
* This method is required by the SPL interface `ArrayAccess`.
* It is implicitly called when you use something like `$value = $vector[$index];`.
* This is equivalent to [[itemAt]].
* @param integer $offset the offset to retrieve item.
* @return mixed the item at the offset
* @throws Exception if the offset is out of range
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment