Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F5992096
VarCloner.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
VarCloner.php
View Options
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace
Symfony\Component\VarDumper\Cloner
;
/**
* @author Nicolas Grekas <p@tchwork.com>
*/
class
VarCloner
extends
AbstractCloner
{
private
static
array
$arrayCache
=
[];
protected
function
doClone
(
mixed
$var
):
array
{
$len
=
1
;
// Length of $queue
$pos
=
0
;
// Number of cloned items past the minimum depth
$refsCounter
=
0
;
// Hard references counter
$queue
=
[[
$var
]];
// This breadth-first queue is the return value
$hardRefs
=
[];
// Map of original zval ids to stub objects
$objRefs
=
[];
// Map of original object handles to their stub object counterpart
$objects
=
[];
// Keep a ref to objects to ensure their handle cannot be reused while cloning
$resRefs
=
[];
// Map of original resource handles to their stub object counterpart
$values
=
[];
// Map of stub objects' ids to original values
$maxItems
=
$this
->
maxItems
;
$maxString
=
$this
->
maxString
;
$minDepth
=
$this
->
minDepth
;
$currentDepth
=
0
;
// Current tree depth
$currentDepthFinalIndex
=
0
;
// Final $queue index for current tree depth
$minimumDepthReached
=
0
===
$minDepth
;
// Becomes true when minimum tree depth has been reached
$cookie
=
(
object
)
[];
// Unique object used to detect hard references
$a
=
null
;
// Array cast for nested structures
$stub
=
null
;
// Stub capturing the main properties of an original item value
// or null if the original value is used directly
$arrayStub
=
new
Stub
();
$arrayStub
->
type
=
Stub
::
TYPE_ARRAY
;
for
(
$i
=
0
;
$i
<
$len
;
++
$i
)
{
// Detect when we move on to the next tree depth
if
(
$i
>
$currentDepthFinalIndex
)
{
++
$currentDepth
;
$currentDepthFinalIndex
=
$len
-
1
;
if
(
$currentDepth
>=
$minDepth
)
{
$minimumDepthReached
=
true
;
}
}
$refs
=
$vals
=
$queue
[
$i
];
foreach
(
$vals
as
$k
=>
$v
)
{
// $v is the original value or a stub object in case of hard references
$zvalRef
=
(
$r
=
\ReflectionReference
::
fromArrayElement
(
$vals
,
$k
))
?
$r
->
getId
()
:
null
;
if
(
$zvalRef
)
{
$vals
[
$k
]
=
&
$stub
;
// Break hard references to make $queue completely
unset
(
$stub
);
// independent from the original structure
if
(
null
!==
$vals
[
$k
]
=
$hardRefs
[
$zvalRef
]
??
null
)
{
$v
=
$vals
[
$k
];
if
(
$v
->
value
instanceof
Stub
&&
(
Stub
::
TYPE_OBJECT
===
$v
->
value
->
type
||
Stub
::
TYPE_RESOURCE
===
$v
->
value
->
type
))
{
++
$v
->
value
->
refCount
;
}
++
$v
->
refCount
;
continue
;
}
$vals
[
$k
]
=
new
Stub
();
$vals
[
$k
]->
value
=
$v
;
$vals
[
$k
]->
handle
=
++
$refsCounter
;
$hardRefs
[
$zvalRef
]
=
$vals
[
$k
];
}
// Create $stub when the original value $v cannot be used directly
// If $v is a nested structure, put that structure in array $a
switch
(
true
)
{
case
null
===
$v
:
case
\is_bool
(
$v
):
case
\is_int
(
$v
):
case
\is_float
(
$v
):
continue
2
;
case
\is_string
(
$v
):
if
(
''
===
$v
)
{
continue
2
;
}
if
(!
preg_match
(
'//u'
,
$v
))
{
$stub
=
new
Stub
();
$stub
->
type
=
Stub
::
TYPE_STRING
;
$stub
->
class
=
Stub
::
STRING_BINARY
;
if
(
0
<=
$maxString
&&
0
<
$cut
=
\strlen
(
$v
)
-
$maxString
)
{
$stub
->
cut
=
$cut
;
$stub
->
value
=
substr
(
$v
,
0
,
-
$cut
);
}
else
{
$stub
->
value
=
$v
;
}
}
elseif
(
0
<=
$maxString
&&
isset
(
$v
[
1
+
(
$maxString
>>
2
)])
&&
0
<
$cut
=
mb_strlen
(
$v
,
'UTF-8'
)
-
$maxString
)
{
$stub
=
new
Stub
();
$stub
->
type
=
Stub
::
TYPE_STRING
;
$stub
->
class
=
Stub
::
STRING_UTF8
;
$stub
->
cut
=
$cut
;
$stub
->
value
=
mb_substr
(
$v
,
0
,
$maxString
,
'UTF-8'
);
}
else
{
continue
2
;
}
$a
=
null
;
break
;
case
\is_array
(
$v
):
if
(!
$v
)
{
continue
2
;
}
$stub
=
$arrayStub
;
$stub
->
class
=
array_is_list
(
$v
)
?
Stub
::
ARRAY_INDEXED
:
Stub
::
ARRAY_ASSOC
;
$a
=
$v
;
break
;
case
\is_object
(
$v
):
if
(
empty
(
$objRefs
[
$h
=
spl_object_id
(
$v
)]))
{
$stub
=
new
Stub
();
$stub
->
type
=
Stub
::
TYPE_OBJECT
;
$stub
->
class
=
$v
::
class
;
$stub
->
value
=
$v
;
$stub
->
handle
=
$h
;
$a
=
$this
->
castObject
(
$stub
,
0
<
$i
);
if
(
$v
!==
$stub
->
value
)
{
if
(
Stub
::
TYPE_OBJECT
!==
$stub
->
type
||
null
===
$stub
->
value
)
{
break
;
}
$stub
->
handle
=
$h
=
spl_object_id
(
$stub
->
value
);
}
$stub
->
value
=
null
;
if
(
0
<=
$maxItems
&&
$maxItems
<=
$pos
&&
$minimumDepthReached
)
{
$stub
->
cut
=
\count
(
$a
);
$a
=
null
;
}
}
if
(
empty
(
$objRefs
[
$h
]))
{
$objRefs
[
$h
]
=
$stub
;
$objects
[]
=
$v
;
}
else
{
$stub
=
$objRefs
[
$h
];
++
$stub
->
refCount
;
$a
=
null
;
}
break
;
default
:
// resource
if
(
empty
(
$resRefs
[
$h
=
(
int
)
$v
]))
{
$stub
=
new
Stub
();
$stub
->
type
=
Stub
::
TYPE_RESOURCE
;
if
(
'Unknown'
===
$stub
->
class
=
@
get_resource_type
(
$v
))
{
$stub
->
class
=
'Closed'
;
}
$stub
->
value
=
$v
;
$stub
->
handle
=
$h
;
$a
=
$this
->
castResource
(
$stub
,
0
<
$i
);
$stub
->
value
=
null
;
if
(
0
<=
$maxItems
&&
$maxItems
<=
$pos
&&
$minimumDepthReached
)
{
$stub
->
cut
=
\count
(
$a
);
$a
=
null
;
}
}
if
(
empty
(
$resRefs
[
$h
]))
{
$resRefs
[
$h
]
=
$stub
;
}
else
{
$stub
=
$resRefs
[
$h
];
++
$stub
->
refCount
;
$a
=
null
;
}
break
;
}
if
(
$a
)
{
if
(!
$minimumDepthReached
||
0
>
$maxItems
)
{
$queue
[
$len
]
=
$a
;
$stub
->
position
=
$len
++;
}
elseif
(
$pos
<
$maxItems
)
{
if
(
$maxItems
<
$pos
+=
\count
(
$a
))
{
$a
=
\array_slice
(
$a
,
0
,
$maxItems
-
$pos
,
true
);
if
(
$stub
->
cut
>=
0
)
{
$stub
->
cut
+=
$pos
-
$maxItems
;
}
}
$queue
[
$len
]
=
$a
;
$stub
->
position
=
$len
++;
}
elseif
(
$stub
->
cut
>=
0
)
{
$stub
->
cut
+=
\count
(
$a
);
$stub
->
position
=
0
;
}
}
if
(
$arrayStub
===
$stub
)
{
if
(
$arrayStub
->
cut
)
{
$stub
=
[
$arrayStub
->
cut
,
$arrayStub
->
class
=>
$arrayStub
->
position
];
$arrayStub
->
cut
=
0
;
}
elseif
(
isset
(
self
::
$arrayCache
[
$arrayStub
->
class
][
$arrayStub
->
position
]))
{
$stub
=
self
::
$arrayCache
[
$arrayStub
->
class
][
$arrayStub
->
position
];
}
else
{
self
::
$arrayCache
[
$arrayStub
->
class
][
$arrayStub
->
position
]
=
$stub
=
[
$arrayStub
->
class
=>
$arrayStub
->
position
];
}
}
if
(!
$zvalRef
)
{
$vals
[
$k
]
=
$stub
;
}
else
{
$hardRefs
[
$zvalRef
]->
value
=
$stub
;
}
}
$queue
[
$i
]
=
$vals
;
}
foreach
(
$values
as
$h
=>
$v
)
{
$hardRefs
[
$h
]
=
$v
;
}
return
$queue
;
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Oct 4 2026, 02:09 (4 w, 3 d ago)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
41/ca/6b9e4deef23dfc2bc8447dabccdc
Default Alt Text
VarCloner.php (9 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment