рдЬрд╝реЗрдВрдб рдлреНрд░реЗрдорд╡рд░реНрдХ: рдПрдХреНрд╕рдПрд╕рдПрд▓ рдФрд░ рд╡реНрдпреВрдЬрд╝ рд╕реЗрд▓реНрдл-рд╕реАрд░рд┐рдпрд▓рд╛рдЗрдЬрд╝реЗрд╢рди

Zend рдлреНрд░реЗрдорд╡рд░реНрдХ: XSL рдФрд░ рд╕реЗрд▓реНрдл-рд╕реАрд░реАрдЬрд╝рд┐рдВрдЧ рд╡реНрдпреВ рдЯреНрд░рд╛рдВрд╕рд▓реЗрд╢рди
рдкреЛрд╕реНрдЯ рдХрд░рдиреЗрд╡рд╛рд▓реЗ: Pascal Opitz

рдореИрдВрдиреЗ рд▓рдВрдмреЗ рд╕рдордп рд╕реЗ рддрд░реНрдХ рджрд┐рдпрд╛ рд╣реИ рдХрд┐ MVC рдлреНрд░реЗрдорд╡рд░реНрдХ рдХреЛ рдЗрдирд▓рд╛рдЗрди PHP рдХреЛрдб рдФрд░ рдЕрдзрд┐рдХ рдХреЗ рдмрдЬрд╛рдп XSL рд╢реИрд▓рд┐рдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рдЗрд╕реАрд▓рд┐рдП рдореИрдВрдиреЗ Zend рдлреНрд░реЗрдорд╡рд░реНрдХ рдХреЙрдиреНрд╕реЗрдкреНрдЯ рдХрд╛ рдереЛрдбрд╝рд╛ рд╕рд╛ рд╕рдмреВрдд рдПрдХ рд╕рд╛рде рдЦрдЯрдЦрдЯрд╛рдпрд╛, рдЬрд╣рд╛рдБ рдлрд╛рдЗрд▓реЛрдВ рдХреЛ XSL рдЯреЗрдореНрдкреНрд▓реЗрдЯ рдХреЗ рд░реВрдк рдореЗрдВ рджрд░реНрд╢рд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдФрд░ рдпрд╣ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП XML рдореЗрдВ рдЦреБрдж рдХреЛ рдХреНрд░рдордмрджреНрдз рдХрд░рддрд╛ рд╣реИред


MVC рдХреА рдореВрд▓ рд╕рдВрд░рдЪрдирд╛


рдореИрдВрдиреЗ рдЕрднреА Zend_Controller рд╕реЗ рдорд╛рдирдХ MVC рд╕рдВрд░рдЪрдирд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рдбреЗрдореЛ рдмрдирд╛рдпрд╛ рд╣реИ:

|
| --- рдбрд┐рдлрд╝реЙрд▓реНрдЯ
| ----- рдирд┐рдпрдВрддреНрд░рдХ
| ----- рдореЙрдбрд▓
| ----- рд╡рд┐рдЪрд╛рд░
| ------- рдлрд┐рд▓реНрдЯрд░
| ------- рдорджрджрдЧрд╛рд░
| ------- рд▓рд┐рдкрд┐рдпрд╛рдБ
| --------- рд╕реВрдЪрдХрд╛рдВрдХ
| --------- рдкрд░реАрдХреНрд╖рдг
|
| --- рдбреЗрдореЛ
| --- zendframework_1.6.2
| -рд╣рд╡рд╛


рдмреЗрд╢рдХ, рдЕрдм рд╣рдореЗрдВ рдПрдХ рдмреВрдЯ рдлрд╛рдЗрд▓ рдХреА рдЬрд░реВрд░рдд рд╣реИ:

set_include_path('.' . PATH_SEPARATOR . '../library/zendframework_1.6.2/' . PATH_SEPARATOR . '../library/demo/' . PATH_SEPARATOR . '../application/default/controllers' . PATH_SEPARATOR . get_include_path()); require_once('Zend/Loader.php'); Zend_Loader::loadClass('Zend_Controller_Front'); Zend_Loader::loadClass('Zend_Controller_Action_Helper_ViewRenderer'); $frontController = Zend_Controller_Front::getInstance(); $frontController->setControllerDirectory(array( 'default' => '../application/default/controllers', )); require_once 'View_Xslt.php'; $view = new View_Xslt; $options = array(); $viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer($view, $options); $viewRenderer->setViewSuffix('xsl'); Zend_Controller_Action_HelperBroker::addHelper($viewRenderer); $frontController->dispatch(); 


рдХреГрдкрдпрд╛ рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдореИрдВрдиреЗ рдПрдХ рдирдпрд╛ рд╡реНрдпреВрдЕрд░реЗрдВрдбрд░ рдФрд░ рдСрдмреНрдЬреЗрдХреНрдЯ рдХрд╛ рдПрдХ рджреГрд╢реНрдп рдкреЗрд╢ рдХрд┐рдпрд╛ рд╣реИ, рдЬрд┐рд╕реЗ View_Xslt.php рд╕реЗ рдкреБрдХрд╛рд░рд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рд▓рд╛рдЗрдмреНрд░реЗрд░реА / рдбреЗрдореЛ рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ рд╕реНрдерд┐рдд рд╣реИред рдореИрдВрдиреЗ XSL рдХреЗ рд▓рд┐рдП рджреГрд╢реНрдп рдкреНрд░рддреНрдпрдп рднреА рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рд╣реИред

рд╕рднреА рдбреЗрдореЛ (рдЬрд╝рд┐рдк рдлреНрд░реЗрдорд╡рд░реНрдХ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдЫреЛрдбрд╝рдХрд░) рдпреБрдХреНрдд рдЬрд╝рд┐рдк рдлрд╝рд╛рдЗрд▓ рдпрд╣рд╛рдБ рдбрд╛рдЙрдирд▓реЛрдб рдХреА рдЬрд╛ рд╕рдХрддреА рд╣реИ ред

рджреГрд╢реНрдп (рджреЗрдЦреЗрдВ)



рджреГрд╢реНрдп рдСрдмреНрдЬреЗрдХреНрдЯ Zend_View_Abstract рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рд╡рд░реНрдЧ рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рджреГрд╢реНрдп _run рдкрджреНрдзрддрд┐ рдореЗрдВ рдкреНрд░рджрд╛рди рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдФрд░ рджреГрд╢реНрдп рдлрд╝рд╛рдЗрд▓ рдХреЛ рдкрд╣рд▓реЗ рддрд░реНрдХ рдХреЗ рд░реВрдк рдореЗрдВ рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рд╣рд╛рд▓рд╛рдБрдХрд┐, рдпрд╣ рддрд░реНрдХ func_get_arg рдХреЗ рд╕рд╛рде рдЙрдкрд▓рдмреНрдз рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП, рдЕрдиреНрдпрдерд╛ рд╣рдо рдПрдХ рд╕рд╛рдл рддреНрд░реБрдЯрд┐ рд╕рдВрджреЗрд╢ рджреЗрддреЗ рд╣реИрдВ рдХрд┐ рд╣рдорд╛рд░рд╛ рдХрдерди Zend_View_Abstract рдХреЗ рд╕рд╛рде рдЕрд╕рдВрдЧрдд рд╣реИред

рдмрд╛рдж рдореЗрдВ рд╕реНрд╡-рдХреНрд░рдордмрджреНрдз рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдореЗрд░реЗ рджреГрд╢реНрдп рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореИрдЬрд┐рдХ рд╡рд┐рдзрд┐ рдореЗрдВ рдПрдХ рдзрд╛рд░рд╛рд╡рд╛рд╣рд┐рдХ рднреА рдЬреЛрдбрд╝рд╛, рд╕рд╛рде рд╣реА рдореИрдВрдиреЗ рдПрдХ рдирд┐рдЬреА рдлрд╝рдВрдХреНрд╢рди рдЬреЛрдбрд╝рд╛ рдЬреЛ рдХрд┐ рд╣рдорд╛рд░реЗ рджреНрд╡рд╛рд░рд╛ рдмрдирд╛рдП рдЧрдП рдзрд╛рд░рд╛рд╡рд╛рд╣рд┐рдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ XML рдореЗрдВ рд╡рд┐рдЪрд╛рд░реЛрдВ рдХреЛ рдХреНрд░рдордмрджреНрдз рдХрд░рддрд╛ рд╣реИред

 require_once('Serializer.php'); class View_Xslt extends Zend_View_Abstract { private $serializer; private $rootName; public function __construct($data = array()) { $this->serializer = new Serializer(); parent::__construct($data); } public function setRootName($name) { $this->rootName = $name; } protected function _run() { $template = func_get_arg(0); $xslDoc = new DOMDocument(); $xslDoc->load($template); $xmlDoc = $this->toXml(); $proc = new XSLTProcessor(); $proc->importStylesheet($xslDoc); echo $proc->transformToXML($xmlDoc); } private function toXml() { $xml_str = $this->serializer->Serialize($this, $this->rootName); return $xml_str; } } 


Serializer (Serializer)


рддреЛ рдпрд╣ рдзрд╛рд░рд╛рд╡рд╛рд╣рд┐рдХ рдХреНрдпрд╛ рдХрд░рддрд╛ рд╣реИ? рдпрд╣ рдПрдХ XML рд╕реНрдЯреНрд░рд┐рдВрдЧ рдореЗрдВ рд╡рд╕реНрддреБрдУрдВ рдХреЛ рдХреНрд░рдорд╛рдВрдХрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░рддрд┐рдмрд┐рдВрдм ( рдкреНрд░рддрд┐рдмрд┐рдВрдм ) рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред рдпрд╣ рд╣рдореЗрдВ рд╣рдорд╛рд░реЗ рдирд┐рдпрдВрддреНрд░рдХ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд╕рд╛рде рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рд╕рд╛рдорд╛рдиреНрдп рдЪрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдмрдирд╛рддрд╛ рд╣реИ, рдмрд╕ $ рдпрд╣ рдХрд╣рдХрд░-> рдлреВ = 'рдмрд╛рд░'ред

рдореИрдВрдиреЗ рдкрд╣рд▓реЗ рдПрдХ рдХреНрд╡рд┐рдХ рдПрдХреНрд╕рдПрдордПрд▓ рд╕реАрд░рд┐рдпрд▓рд╛рдЗрдЬрд╝реЗрд╢рди рдкреЛрд╕реНрдЯ рдХрд┐рдпрд╛ рд╣реИ, рдФрд░ рдореИрдВрдиреЗ рдЬреЛ рд╕реАрд░рд┐рдпрд▓рд╛рдЗрдЬрд╝рд░ рдкреНрд░рд╕реНрддреБрдд рдХрд┐рдпрд╛ рд╣реИ, рд╡рд╣ рдореБрдЭреЗ рд╡рд╣рд╛рдВ рдорд┐рд▓реА рдкреНрд░реЗрд░рдгрд╛ рд╕реЗ рдкреНрд░реЗрд░рд┐рдд рд╣реИред рд╕рд╛рд╡рдзрд╛рдиреА: рдзреНрдпрд╛рди рд░рдЦреЗрдВ рдХрд┐ рдпрд╣ рд╕рд┐рд░реНрдл рдЕрд╡рдзрд╛рд░рдгрд╛ рдХрд╛ рдПрдХ рдкреНрд░рдорд╛рдг рд╣реИ, рдФрд░ рд╕рд░реНрд╡реЛрддреНрддрдо рдкрд░рд┐рдгрд╛рдо рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╢рд╛рдпрдж рдереЛрдбрд╝рд╛ рдФрд░ рдХрд╛рдо рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИред

 class Serializer { private $xmlDoc; public function __construct() { $this->xmlDoc = new DOMDocument(); } public function Serialize($inst, $nodeName=null) { if(is_object($inst)) { $nodeName = ($nodeName == null) ? get_class($inst) : $nodeName; $root = $this->xmlDoc->createElement($nodeName); $this->xmlDoc->appendChild($root); $this->SerializeObject($inst, $nodeName, $root); } else if(is_array($inst)) { $nodeName = ($nodeName == null) ? get_class($inst) : $nodeName; $root = $this->xmlDoc->createElement($nodeName); $this->xmlDoc->appendChild($root); $this->SerializeArray($inst, $nodeName, $root); } return $this->xmlDoc; } private function SerializeObject($inst, $nodeName, $parent) { $obj = new ReflectionObject($inst); $properties = $obj->getProperties(); foreach($properties as $prop) { if(!$prop->isPrivate()) { $elem = $this->SerializeData($prop->getName(), $prop->getValue($inst), $parent); } } } private function SerializeArray($array, $nodeName, $parent) { foreach($array as $key => $val) { $keyStr = (is_numeric($key)) ? 'ArrayValue' : $key; $elem = $this->SerializeData($keyStr, $val, $parent); if(is_numeric($key)) { $elem->setAttribute('index', $key); } } } private function SerializeData($key, $val, $parent) { if(is_object($val)) { $propNodeName = get_class($val); $elem = $this->xmlDoc->createElement($propNodeName); $parent->appendChild($elem); $this->SerializeObject($val, $propNodeName, $parent); $elem->setAttribute('type', 'object'); } else if(is_array($val)) { $elem = $this->xmlDoc->createElement($key); $parent->appendChild($elem); $this->SerializeArray($val, $key, $elem); $elem->setAttribute('type', 'array'); } else { $elem = $this->xmlDoc->createElement($key, $val); $parent->appendChild($elem); $elem->setAttribute('type', 'property'); } return $elem; } } 


рдирд┐рдпрдВрддреНрд░рдХ рдФрд░ рджреЗрдЦреЗрдВ рдлрд╝рд╛рдЗрд▓реЗрдВ



рд▓рдЧрднрдЧ рд╕рдм рдХреБрдЫред рд╣рдореЗрдВ рдХрд╛рдо рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдбреЗрдореЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╕ рдХреБрдЫ рдПрдХреНрд╕рдПрд╕рдПрд▓ рдлрд╝рд╛рдЗрд▓реЛрдВ рдФрд░ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рдирд┐рдпрдВрддреНрд░рдХ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдкрд╣рд▓рд╛ рдирд┐рдпрдВрддреНрд░рдХ рдФрд░ рдХреНрд░рд┐рдпрд╛ред рдореИрдВрдиреЗ рдПрдХ рдЫреЛрдЯреЗ рд╕реЗ рдбреЗрдореЛ рдХреНрд▓рд╛рд╕ рдХреЛ рд╢рд╛рдорд┐рд▓ рдХрд┐рдпрд╛ рддрд╛рдХрд┐ рд╣рдо рдзрд╛рд░рд╛рд╡рд╛рд╣рд┐рдХ рдХреЛ рдПрдХреНрд╢рди рдореЗрдВ рджреЗрдЦ рд╕рдХреЗрдВ:

 class IndexController extends Zend_Controller_Action { public function indexAction() { $this->view->setRootName('DataObject'); $this->view->foo = 'bar'; $this->view->super = array( 'here' => 'there', 'foo' => array(1,2,'test'), ); $this->view->testObject = new DemoObject(); $this->view->testObject->var = 'testObjectVar'; } } class DemoObject {} 


рдлрд╝рд╛рдЗрд▓ рджреЗрдЦреЗрдВред рд╣рдо рдХреЗрд╡рд▓ рдПрдХ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдХреНрдпреЛрдВрдХрд┐ рдореИрдВ Zend_Layout рдХреЛ рдкрдХрдбрд╝рдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛, рдореИрдВрдиреЗ xsl рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд┐рдпрд╛: рдХреБрдЫ рдЗрд╕реА рддрд░рд╣ рд╕реЗ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдпрд╛рддред

 <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:import href="../layout.xsl"/> <xsl:template match="DataObject"> <xsl:apply-templates select="*" /> </xsl:template> <xsl:template match="*"> <div> <h2><xsl:value-of select="name()" /></h2> <xsl:apply-templates select="text()" /> <xsl:apply-templates select="*" /> </div> </xsl:template> </xsl:stylesheet> 


 <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" encoding="ISO-8859-1" omit-xml-declaration="no" doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" indent="yes" /> <xsl:template match="/"> <html> <head> <title>Test</title> </head> <body> <xsl:apply-templates select="/*" /> </body> </html> </xsl:template> </xsl:stylesheet> 


рдкрд░рд┐рдгрд╛рдо


рдФрд░ рдпрд╣рд╛рдБ рдпрд╣ рд╣реИ! рдкрд░рд┐рдгрд╛рдореА рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛ рдкреГрд╖реНрда рдЖрдкрдХреЛ рдЖрдЙрдЯрдкреБрдЯ рдореЗрдВ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рджреЗрдирд╛ рдЪрд╛рд╣рд┐рдП:

 <?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" /> <title>Test</title> </head> <body> <div><h2>foo</h2>bar</div> <div> <h2>super</h2> <div><h2>here</h2>there</div> <div> <h2>foo</h2> <div><h2>ArrayValue</h2>1</div> <div><h2>ArrayValue</h2>2</div> <div><h2>ArrayValue</h2>test</div> </div> </div> <div> <h2>DemoObject</h2> </div> <div><h2>var</h2>testObjectVar</div> </body> </html> 





рдРрд╕рд╛ рд╣реБрдЖ рдХрд┐ рдореИрдВрдиреЗ рд▓рдВрдмреЗ рд╕рдордп рддрдХ XML рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд┐рдпрд╛ рдФрд░ рдореИрдВ рдХрд╛рдо рдХреЗ рд▓рд┐рдП ZendFramework рдореЗрдВ XSLT рдЯреЗрдореНрдкрд▓реЗрдЯ рдЗрдВрдЬрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛, рдФрд░ рдпрд╣ рдПрдХрдорд╛рддреНрд░ рдРрд╕рд╛ рд▓реЗрдЦ рд╣реИ рдЬрд┐рд╕реЗ рдореИрдВрдиреЗ рдвреВрдВрдврдиреЗ рдореЗрдВ рдХрд╛рдордпрд╛рдмреА рд╣рд╛рд╕рд┐рд▓ рдХреА рдЬреЛ рдореБрдЭреЗ рдЗрд╕ рдЗрдЪреНрдЫрд╛ рдХреЛ рдкреВрд░рд╛ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред

рдирддреАрдЬрддрди, рдореБрдЭреЗ рдПрдХ рд╕рд░рд▓ рдкреНрд░рдгрд╛рд▓реА рдорд┐рд▓реА рдЬрд╣рд╛рдВ рдЗрдВрдЬрди рдФрд░ рдорд╛рдирдХ рдЯреЗрдореНрдкрд▓реЗрдЯреНрд╕ рдХрд╛ рдПрдХ рд╕реЗрдЯ рдЫреЛрдЯреЗ рд╡реНрдпрд╡рд╕рд╛рдп рдХрд╛рд░реНрдб рд╕рд╛рдЗрдЯреЛрдВ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рддрд╛ рдерд╛, рдФрд░ рдЙрдирд╕реЗ рд╕рд╛рдордЧреНрд░реА рдХреЛ рдбреЗрдЯрд╛ рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ xml рдлрд╝рд╛рдЗрд▓реЛрдВ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдФрд░ рдбреЗрдЯрд╛рдмреЗрд╕ рд╕реЗ рд╕рд┐рд░рджрд░реНрдж рдХреЗ рдмрд┐рдирд╛, рд╣реЛрд╕реНрдЯрд┐рдВрдЧ рд╕реЗ рд╣реЛрд╕реНрдЯрд┐рдВрдЧ рддрдХ рд╕рднреА рдорд╛рдЗрдЧреНрд░реЗрд╢рди рд╕рд░рд▓ рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рджреНрд╡рд╛рд░рд╛ рдХрд┐рдП рдЧрдПред рдФрд░ рдкреНрд░рдХрд╛рд╢рд┐рдд рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ рдХреЗрд╡рд▓ рд╕реАрдПрд╕рдПрд╕, рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдФрд░ рдЪрд┐рддреНрд░ рд╢рд╛рдорд┐рд▓ рдереЗред

Source: https://habr.com/ru/post/In166631/


All Articles