Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F1431224
OutputFormatter.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
OutputFormatter.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\Console\Formatter
;
use
Symfony\Component\Console\Exception\InvalidArgumentException
;
use
function
Symfony\Component\String\b
;
/**
* Formatter class for console output.
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
* @author Roland Franssen <franssen.roland@gmail.com>
*/
class
OutputFormatter
implements
WrappableOutputFormatterInterface
{
private
array
$styles
=
[];
private
OutputFormatterStyleStack
$styleStack
;
public
function
__clone
()
{
$this
->
styleStack
=
clone
$this
->
styleStack
;
foreach
(
$this
->
styles
as
$key
=>
$value
)
{
$this
->
styles
[
$key
]
=
clone
$value
;
}
}
/**
* Escapes "<" and ">" special chars in given text.
*/
public
static
function
escape
(
string
$text
):
string
{
$text
=
preg_replace
(
'/([^
\\\\
]|^)([<>])/'
,
'$1
\\\\
$2'
,
$text
);
return
self
::
escapeTrailingBackslash
(
$text
);
}
/**
* Escapes trailing "\" in given text.
*
* @internal
*/
public
static
function
escapeTrailingBackslash
(
string
$text
):
string
{
if
(
str_ends_with
(
$text
,
'
\\
'
))
{
$len
=
\strlen
(
$text
);
$text
=
rtrim
(
$text
,
'
\\
'
);
$text
=
str_replace
(
"
\0
"
,
''
,
$text
);
$text
.=
str_repeat
(
"
\0
"
,
$len
-
\strlen
(
$text
));
}
return
$text
;
}
/**
* Initializes console output formatter.
*
* @param OutputFormatterStyleInterface[] $styles Array of "name => FormatterStyle" instances
*/
public
function
__construct
(
private
bool
$decorated
=
false
,
array
$styles
=
[],
)
{
$this
->
setStyle
(
'error'
,
new
OutputFormatterStyle
(
'white'
,
'red'
));
$this
->
setStyle
(
'info'
,
new
OutputFormatterStyle
(
'green'
));
$this
->
setStyle
(
'comment'
,
new
OutputFormatterStyle
(
'yellow'
));
$this
->
setStyle
(
'question'
,
new
OutputFormatterStyle
(
'black'
,
'cyan'
));
foreach
(
$styles
as
$name
=>
$style
)
{
$this
->
setStyle
(
$name
,
$style
);
}
$this
->
styleStack
=
new
OutputFormatterStyleStack
();
}
public
function
setDecorated
(
bool
$decorated
):
void
{
$this
->
decorated
=
$decorated
;
}
public
function
isDecorated
():
bool
{
return
$this
->
decorated
;
}
public
function
setStyle
(
string
$name
,
OutputFormatterStyleInterface
$style
):
void
{
$this
->
styles
[
strtolower
(
$name
)]
=
$style
;
}
public
function
hasStyle
(
string
$name
):
bool
{
return
isset
(
$this
->
styles
[
strtolower
(
$name
)]);
}
public
function
getStyle
(
string
$name
):
OutputFormatterStyleInterface
{
if
(!
$this
->
hasStyle
(
$name
))
{
throw
new
InvalidArgumentException
(
\sprintf
(
'Undefined style: "%s".'
,
$name
));
}
return
$this
->
styles
[
strtolower
(
$name
)];
}
public
function
format
(?
string
$message
):
?
string
{
return
$this
->
formatAndWrap
(
$message
,
0
);
}
public
function
formatAndWrap
(?
string
$message
,
int
$width
):
string
{
if
(
null
===
$message
)
{
return
''
;
}
$offset
=
0
;
$output
=
''
;
$openTagRegex
=
'[a-z](?:[^
\\\\
<>]*+ |
\\\\
.)*'
;
$closeTagRegex
=
'[a-z][^<>]*+'
;
$currentLineLength
=
0
;
preg_match_all
(
"#<(($openTagRegex) | /($closeTagRegex)?)>#ix"
,
$message
,
$matches
,
\PREG_OFFSET_CAPTURE
);
foreach
(
$matches
[
0
]
as
$i
=>
$match
)
{
$pos
=
$match
[
1
];
$text
=
$match
[
0
];
if
(
0
!=
$pos
&&
'
\\
'
==
$message
[
$pos
-
1
])
{
continue
;
}
// add the text up to the next tag
$output
.=
$this
->
applyCurrentStyle
(
substr
(
$message
,
$offset
,
$pos
-
$offset
),
$output
,
$width
,
$currentLineLength
);
$offset
=
$pos
+
\strlen
(
$text
);
// opening tag?
if
(
$open
=
'/'
!==
$text
[
1
])
{
$tag
=
$matches
[
1
][
$i
][
0
];
}
else
{
$tag
=
$matches
[
3
][
$i
][
0
]
??
''
;
}
if
(!
$open
&&
!
$tag
)
{
// </>
$this
->
styleStack
->
pop
();
}
elseif
(
null
===
$style
=
$this
->
createStyleFromString
(
$tag
))
{
$output
.=
$this
->
applyCurrentStyle
(
$text
,
$output
,
$width
,
$currentLineLength
);
}
elseif
(
$open
)
{
$this
->
styleStack
->
push
(
$style
);
}
else
{
$this
->
styleStack
->
pop
(
$style
);
}
}
$output
.=
$this
->
applyCurrentStyle
(
substr
(
$message
,
$offset
),
$output
,
$width
,
$currentLineLength
);
return
strtr
(
$output
,
[
"
\0
"
=>
'
\\
'
,
'
\\
<'
=>
'<'
,
'
\\
>'
=>
'>'
]);
}
public
function
getStyleStack
():
OutputFormatterStyleStack
{
return
$this
->
styleStack
;
}
/**
* Tries to create new style instance from string.
*/
private
function
createStyleFromString
(
string
$string
):
?
OutputFormatterStyleInterface
{
if
(
isset
(
$this
->
styles
[
$string
]))
{
return
$this
->
styles
[
$string
];
}
if
(!
preg_match_all
(
'/([^=]+)=([^;]+)(;|$)/'
,
$string
,
$matches
,
\PREG_SET_ORDER
))
{
return
null
;
}
$style
=
new
OutputFormatterStyle
();
foreach
(
$matches
as
$match
)
{
array_shift
(
$match
);
$match
[
0
]
=
strtolower
(
$match
[
0
]);
if
(
'fg'
==
$match
[
0
])
{
$style
->
setForeground
(
strtolower
(
$match
[
1
]));
}
elseif
(
'bg'
==
$match
[
0
])
{
$style
->
setBackground
(
strtolower
(
$match
[
1
]));
}
elseif
(
'href'
===
$match
[
0
])
{
$url
=
preg_replace
(
'{
\\\\
([<>])}'
,
'$1'
,
$match
[
1
]);
$style
->
setHref
(
$url
);
}
elseif
(
'options'
===
$match
[
0
])
{
preg_match_all
(
'([^,;]+)'
,
strtolower
(
$match
[
1
]),
$options
);
$options
=
array_shift
(
$options
);
foreach
(
$options
as
$option
)
{
$style
->
setOption
(
$option
);
}
}
else
{
return
null
;
}
}
return
$style
;
}
/**
* Applies current style from stack to text, if must be applied.
*/
private
function
applyCurrentStyle
(
string
$text
,
string
$current
,
int
$width
,
int
&
$currentLineLength
):
string
{
if
(
''
===
$text
)
{
return
''
;
}
if
(!
$width
)
{
return
$this
->
isDecorated
()
?
$this
->
styleStack
->
getCurrent
()->
apply
(
$text
)
:
$text
;
}
if
(!
$currentLineLength
&&
''
!==
$current
)
{
$text
=
ltrim
(
$text
);
}
if
(
$currentLineLength
)
{
$prefix
=
substr
(
$text
,
0
,
$i
=
$width
-
$currentLineLength
).
"
\n
"
;
$text
=
substr
(
$text
,
$i
);
}
else
{
$prefix
=
''
;
}
preg_match
(
'~(
\\
n)$~'
,
$text
,
$matches
);
$text
=
$prefix
.
$this
->
addLineBreaks
(
$text
,
$width
);
$text
=
rtrim
(
$text
,
"
\n
"
).(
$matches
[
1
]
??
''
);
if
(!
$currentLineLength
&&
''
!==
$current
&&
!
str_ends_with
(
$current
,
"
\n
"
))
{
$text
=
"
\n
"
.
$text
;
}
$lines
=
explode
(
"
\n
"
,
$text
);
foreach
(
$lines
as
$line
)
{
$currentLineLength
+=
\strlen
(
$line
);
if
(
$width
<=
$currentLineLength
)
{
$currentLineLength
=
0
;
}
}
if
(
$this
->
isDecorated
())
{
foreach
(
$lines
as
$i
=>
$line
)
{
$lines
[
$i
]
=
$this
->
styleStack
->
getCurrent
()->
apply
(
$line
);
}
}
return
implode
(
"
\n
"
,
$lines
);
}
private
function
addLineBreaks
(
string
$text
,
int
$width
):
string
{
$encoding
=
mb_detect_encoding
(
$text
,
null
,
true
)
?:
'UTF-8'
;
return
b
(
$text
)->
toCodePointString
(
$encoding
)->
wordwrap
(
$width
,
"
\n
"
,
true
)->
toByteString
(
$encoding
);
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Sat, May 16, 20:12 (20 h, 39 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
76/ef/eb92f38ea7bae61648daba55447e
Default Alt Text
OutputFormatter.php (7 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment