Initial Commit

This commit is contained in:
2019-11-21 12:25:31 +01:00
commit f4aabcb9b1
13959 changed files with 787761 additions and 0 deletions

View File

@@ -0,0 +1,49 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace TheliaSmarty\Tests\Template\Plugin\Controller;
use Thelia\Controller\Front\BaseFrontController;
use Thelia\Core\HttpFoundation\Response;
/**
* Class TestController
* @package TheliaSmarty\Tests\Template\Plugin\Controller
* @author Benjamin Perche <bperche@openstudio.fr>
*/
class TestController extends BaseFrontController
{
public function testAction()
{
return new Response("world");
}
public function testParamsAction($paramA, $paramB)
{
return new Response($paramA.$paramB);
}
public function testMethodAction()
{
return $this->getRequest()->getMethod();
}
public function testQueryAction()
{
return $this->getRequest()->query->get("foo");
}
public function testRequestAction()
{
return $this->getRequest()->request->get("foo").$this->getRequest()->getMethod();
}
}

View File

@@ -0,0 +1,186 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace TheliaSmarty\Tests\Template\Plugin;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Form\Extension\Core\CoreExtension;
use Symfony\Component\Form\FormFactoryBuilder;
use Symfony\Component\Validator\ValidatorBuilder;
use TheliaSmarty\Template\Plugins\Form;
/**
* Class FormTest
* @package TheliaSmarty\Tests\Template\Plugin
* @author Benjamin Perche <benjamin@thelia.net>
*/
class FormTest extends SmartyPluginTestCase
{
/**
* @var Form
*/
protected $plugin;
/**
* @return \TheliaSmarty\Template\AbstractSmartyPlugin
*/
protected function getPlugin(ContainerBuilder $container)
{
$this->plugin = new Form(
$container->get("thelia.form_factory"),
$container->get("thelia.parser.context"),
$container->get("thelia.parser")
);
$this->plugin->setFormDefinition($container->get("thelia.parser.forms"));
return $this->plugin;
}
public function testSimpleStackedForm()
{
$parserContext = $this->getParserContext();
$this->assertNull($parserContext->popCurrentForm());
// First, initialize form
// eq: {form name="thelia.empty"}
$repeat = true;
$this->plugin->generateForm(
["name" => "thelia.empty"],
"",
$this->getMock("\\Smarty_Internal_Template", [], [], '', false),
$repeat
);
// Here, the current form is present
$this->assertInstanceOf("Thelia\\Form\\EmptyForm", $parserContext->getCurrentForm());
$this->assertInstanceOf("Thelia\\Form\\EmptyForm", $form = $parserContext->popCurrentForm());
// But not after we have pop
$this->assertNull($parserContext->popCurrentForm());
// So we re-push it into the stack
$parserContext->pushCurrentForm($form);
// And run the ending form tag
// eq: {/form}
$repeat = false;
$this->plugin->generateForm(
["name" => "thelia.empty"],
"",
$this->getMock("\\Smarty_Internal_Template", [], [], '', false),
$repeat
);
// There is no more form in the stack
$this->assertNull($parserContext->popCurrentForm());
// Let's even predict an exception
$this->setExpectedException(
"TheliaSmarty\\Template\\Exception\\SmartyPluginException",
"There is currently no defined form"
);
$parserContext->getCurrentForm();
}
public function testMultipleStackedForms()
{
$parserContext = $this->getParserContext();
$this->assertNull($parserContext->popCurrentForm());
// First form:
// eq: {form name="thelia.empty"}
$repeat = true;
$this->plugin->generateForm(
["name" => "thelia.empty"],
"",
$this->getMock("\\Smarty_Internal_Template", [], [], '', false),
$repeat
);
$this->assertInstanceOf("Thelia\\Form\\EmptyForm", $parserContext->getCurrentForm());
// Then next one:
// eq: {form name="thelia.api.empty"}
$repeat = true;
$this->plugin->generateForm(
["name" => "thelia.api.empty"],
"",
$this->getMock("\\Smarty_Internal_Template", [], [], '', false),
$repeat
);
$this->assertInstanceOf("Thelia\\Form\\Api\\ApiEmptyForm", $parserContext->getCurrentForm());
// Third form:
// eq: {form name="thelia.empty.2"}
$repeat = true;
$this->plugin->generateForm(
["name" => "thelia.empty.2"],
"",
$this->getMock("\\Smarty_Internal_Template", [], [], '', false),
$repeat
);
$this->assertInstanceOf("Thelia\\Form\\EmptyForm", $parserContext->getCurrentForm());
// Then, Let's close forms
// eq: {/form} {* related to {form name="thelia.empty.2"} *}
$repeat = false;
$this->plugin->generateForm(
["name" => "thelia.empty.2"],
"",
$this->getMock("\\Smarty_Internal_Template", [], [], '', false),
$repeat
);
$this->assertInstanceOf("Thelia\\Form\\Api\\ApiEmptyForm", $parserContext->getCurrentForm());
// Then, Let's close forms
// eq: {/form} {* related to {form name="thelia.api.empty"} *}
$repeat = false;
$this->plugin->generateForm(
["name" => "thelia.api.empty"],
"",
$this->getMock("\\Smarty_Internal_Template", [], [], '', false),
$repeat
);
$this->assertInstanceOf("Thelia\\Form\\EmptyForm", $parserContext->getCurrentForm());
// Then close the first form:
// eq: {/form} {* related to {form name="thelia.empty"} *}
$repeat = false;
$this->plugin->generateForm(
["name" => "thelia.empty"],
"",
$this->getMock("\\Smarty_Internal_Template", [], [], '', false),
$repeat
);
// The exception
$this->setExpectedException(
"TheliaSmarty\\Template\\Exception\\SmartyPluginException",
"There is currently no defined form"
);
$parserContext->getCurrentForm();
}
/**
* @return \Thelia\Core\Template\ParserContext
*/
protected function getParserContext()
{
return $this->container->get("thelia.parser.context");
}
}

View File

@@ -0,0 +1,234 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace TheliaSmarty\Tests\Template\Plugin;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpFoundation\RequestStack;
use Thelia\Core\HttpFoundation\Request;
use Thelia\Model\AddressQuery;
use Thelia\Model\CountryQuery;
use Thelia\Model\CurrencyQuery;
use Thelia\Model\StateQuery;
use TheliaSmarty\Template\Plugins\Format;
/**
* Class FormatTest
* @package TheliaSmarty\Tests\Template\Plugin
* @author Gilles Bourgeat <gbourgeat@openstudio.fr>
* @author Baixas Alban <abaixas@openstudio.fr>
*/
class FormatTest extends SmartyPluginTestCase
{
/** @var RequestStack */
protected $requestStack;
public function testFormatTwoDimensionalArray()
{
$requestStack = new RequestStack();
$requestStack->push(new Request());
$plugin = new Format($requestStack);
$params['values'] = [
'Colors' => ['Green', 'Yellow', 'Red'],
'Material' => ['Wood']
];
$output = $plugin->formatTwoDimensionalArray($params);
$this->assertEquals(
"Colors : Green / Yellow / Red | Material : Wood",
$output
);
}
public function testFormatMoneyNotForceCurrency()
{
// new format_money method, thelia >= 2.3
$data = $this->render("testFormatMoney.html", [
'number' => 9.9999
]);
$this->assertEquals("10.00 €", $data);
}
public function testFormatMoneyForceCurrency()
{
/********************/
/*** Test for EUR ***/
/********************/
$currency = CurrencyQuery::create()->findOneByCode('EUR');
// new format_money method, thelia >= 2.3
$data = $this->render("testFormatMoney.html", [
'number' => 9.9999,
'currency' => $currency->getId()
]);
$this->assertEquals("10.00 " . $currency->getSymbol(), $data);
// old format_money method, thelia < 2.3
$data = $this->render("testFormatMoney.html", [
'number' => 9.9999,
'currency_symbol' => $currency->getSymbol()
]);
$this->assertEquals("10.00 " . $currency->getSymbol(), $data);
/********************/
/*** Test for USD ***/
/********************/
$currency = CurrencyQuery::create()->findOneByCode('USD');
// new format_money method, thelia >= 2.3
$data = $this->render("testFormatMoney.html", [
'number' => 9.9999,
'currency' => $currency->getId()
]);
$this->assertEquals($currency->getSymbol() . "10.00", $data);
// old format_money method, thelia < 2.3
$data = $this->render("testFormatMoney.html", [
'number' => 9.9999,
'currency_symbol' => $currency->getSymbol()
]);
$this->assertEquals($currency->getSymbol() . "10.00", $data);
/********************/
/*** Test for GBP ***/
/********************/
$currency = CurrencyQuery::create()->findOneByCode('GBP');
// new format_money method, thelia >= 2.3
$data = $this->render("testFormatMoney.html", [
'number' => 9.9999,
'currency' => $currency->getId()
]);
$this->assertEquals($currency->getSymbol() . "10.00", $data);
// old format_money method, thelia < 2.3
$data = $this->render("testFormatMoney.html", [
'number' => 9.9999,
'currency_symbol' => $currency->getSymbol()
]);
$this->assertEquals($currency->getSymbol() . "10.00", $data);
}
public function testFormatAddress()
{
// Test for address in France
$countryFR = CountryQuery::create()->filterByIsoalpha2('FR')->findOne();
$address = AddressQuery::create()->findOne();
$address
->setCountryId($countryFR->getId())
->save();
$data = $this->renderString(
'{format_address address=$address locale="fr_FR"}',
[
'address' => $address->getId()
]
);
$title = $address->getCustomerTitle()
->setLocale('fr_FR')
->getShort();
$expected = [
'<p >',
sprintf('<span class="recipient">%s %s %s</span><br>', $title, $address->getLastname(), $address->getFirstname()),
sprintf('<span class="address-line1">%s</span><br>', $address->getAddress1()),
sprintf('<span class="postal-code">%s</span> <span class="locality">%s</span><br>', $address->getZipcode(), $address->getCity()),
'<span class="country">France</span>',
'</p>'
];
$this->assertEquals($data, implode("\n", $expected));
// Test for address in USA
$stateDC = StateQuery::create()->filterByIsocode('DC')->findOne();
$countryUS = $stateDC->getCountry();
$address
->setCountryId($countryUS->getId())
->setStateId($stateDC->getId())
->save();
$data = $this->renderString(
'{format_address address=$address locale="en_US"}',
[
'address' => $address->getId()
]
);
$title = $address->getCustomerTitle()
->setLocale('en_US')
->getShort();
$expected = [
'<p >',
sprintf('<span class="recipient">%s %s %s</span><br>', $title, $address->getLastname(), $address->getFirstname()),
sprintf('<span class="address-line1">%s</span><br>', $address->getAddress1()),
sprintf(
'<span class="locality">%s</span>, <span class="administrative-area">%s</span> <span class="postal-code">%s</span><br>',
$address->getCity(),
$stateDC->getIsocode(),
$address->getZipcode()
),
'<span class="country">United States</span>',
'</p>'
];
$this->assertEquals($data, implode("\n", $expected));
// Test html tag
$data = $this->renderString(
'{format_address html_tag="address" html_class="a_class" html_id="an_id" address=$address}',
['address' => $address->getId()]
);
$this->assertTrue(strpos($data, '<address class="a_class" id="an_id">') !== false);
// Test plain text
$data = $this->renderString(
'{format_address html="0" address=$address locale="en_US"}',
[
'address' => $address->getId()
]
);
$expected = [
sprintf('%s %s %s', $title, $address->getLastname(), $address->getFirstname()),
sprintf('%s', $address->getAddress1()),
sprintf('%s, %s %s', $address->getCity(), $stateDC->getIsocode(), $address->getZipcode()),
'United States',
];
$this->assertEquals($data, implode("\n", $expected));
}
/**
* @param ContainerBuilder $container
* @return \TheliaSmarty\Template\AbstractSmartyPlugin
*/
protected function getPlugin(ContainerBuilder $container)
{
$this->requestStack = $container->get("request_stack");
return new Format($this->requestStack);
}
}

View File

@@ -0,0 +1,80 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace TheliaSmarty\Tests\Template\Plugin;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use TheliaSmarty\Template\Plugins\Render;
use Thelia\Core\Controller\ControllerResolver;
/**
* Class RenderTest
* @package TheliaSmarty\Tests\Template\Plugin
* @author Benjamin Perche <bperche@openstudio.fr>
*/
class RenderTest extends SmartyPluginTestCase
{
public function testRenderWithoutParams()
{
$data = $this->render("test.html");
$this->assertEquals("Hello, world!", $data);
}
public function testRenderWithParams()
{
$data = $this->render("testParams.html");
$this->assertEquals("Hello, world!", $data);
}
public function testMethodParameter()
{
$data = $this->render("testMethod.html");
$this->assertEquals("PUT", $data);
}
public function testQueryArrayParamater()
{
$this->smarty->assign("query", ["foo" => "bar"]);
$data = $this->render("testQueryArray.html");
$this->assertEquals("bar", $data);
}
public function testQueryStringParamater()
{
$data = $this->render("testQueryString.html");
$this->assertEquals("bar", $data);
}
public function testRequestParamater()
{
$data = $this->render("testRequest.html");
$this->assertEquals("barPOSTbazPUT", $data);
}
/**
* @return \TheliaSmarty\Template\AbstractSmartyPlugin
*/
protected function getPlugin(ContainerBuilder $container)
{
return new Render(
new ControllerResolver($container),
$container->get("request_stack"),
$container
);
}
}

View File

@@ -0,0 +1,112 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace TheliaSmarty\Tests\Template\Plugin;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Form\Extension\Core\CoreExtension;
use Symfony\Component\Form\FormFactoryBuilder;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Validator\ValidatorBuilder;
use Thelia\Core\Form\TheliaFormFactory;
use Thelia\Core\Form\TheliaFormValidator;
use Thelia\Core\HttpFoundation\Request;
use Thelia\Core\HttpFoundation\Session\Session;
use Thelia\Core\Template\ParserContext;
use Thelia\Core\Template\TheliaTemplateHelper;
use Thelia\Core\Translation\Translator;
use Thelia\Tests\ContainerAwareTestCase;
use TheliaSmarty\Template\SmartyParser;
/**
* Class SmartyPluginTestCase
* @package TheliaSmarty\Tests\Template\Plugin
* @author Benjamin Perche <bperche@openstudio.fr>
*/
abstract class SmartyPluginTestCase extends ContainerAwareTestCase
{
/** @var SmartyParser */
protected $smarty;
/**
* @param ContainerBuilder $container
* Use this method to build the container with the services that you need.
*/
protected function buildContainer(ContainerBuilder $container)
{
/** @var Request $request */
$request = $container->get("request_stack")->getCurrentRequest();
if (null === $request->getSession()) {
$request->setSession(new Session());
}
$requestStack = new RequestStack();
$requestStack->push($request);
$container->set("thelia.parser.forms", [
"thelia.empty" => "Thelia\\Form\\EmptyForm",
"thelia.empty.2" => "Thelia\\Form\\EmptyForm",
"thelia.api.empty" => "Thelia\\Form\\Api\\ApiEmptyForm",
]);
$container->set("thelia.form_factory_builder", (new FormFactoryBuilder())->addExtension(new CoreExtension()));
$container->set("thelia.forms.validator_builder", new ValidatorBuilder());
$container->set(
"thelia.form_factory",
new TheliaFormFactory($requestStack, $container, $container->get("thelia.parser.forms"))
);
$container->set("thelia.parser.context", new ParserContext(
$requestStack,
$container->get("thelia.form_factory"),
new TheliaFormValidator(new Translator($container), 'dev')
));
$this->smarty = new SmartyParser(
$requestStack,
$container->get("event_dispatcher"),
$container->get("thelia.parser.context"),
$templateHelper = new TheliaTemplateHelper()
);
$container->set("thelia.parser", $this->smarty);
$this->smarty->addPlugins($this->getPlugin($container));
$this->smarty->registerPlugins();
}
protected function render($template, $data = [])
{
return $this->internalRender('file', __DIR__.DS."fixtures".DS.$template, $data);
}
protected function renderString($template, $data = [])
{
return $this->internalRender('string', $template, $data);
}
protected function internalRender($resourceType, $resourceContent, array $data)
{
foreach ($data as $key => $value) {
$this->smarty->assign($key, $value);
}
return $this->smarty->fetch(sprintf("%s:%s", $resourceType, $resourceContent));
}
/**
* @param ContainerBuilder $container
* @return \TheliaSmarty\Template\AbstractSmartyPlugin
*/
abstract protected function getPlugin(ContainerBuilder $container);
}

View File

@@ -0,0 +1 @@
Hello, {render action="TheliaSmarty\Tests\Template\Plugin:Test:test"}!

View File

@@ -0,0 +1 @@
{if $currency}{format_money number=$number currency_id=$currency}{else}{format_money number=$number symbol=$currency_symbol}{/if}

View File

@@ -0,0 +1 @@
{render action="TheliaSmarty\Tests\Template\Plugin:Test:testMethod" method="PUT"}

View File

@@ -0,0 +1 @@
{render action="TheliaSmarty\Tests\Template\Plugin:Test:testParams" paramA="Hello, " paramB="world!"}

View File

@@ -0,0 +1 @@
{render action="TheliaSmarty\Tests\Template\Plugin:Test:testQuery" query=$query}

View File

@@ -0,0 +1 @@
{render action="TheliaSmarty\Tests\Template\Plugin:Test:testQuery" query="foo=bar"}

View File

@@ -0,0 +1 @@
{render action="TheliaSmarty\Tests\Template\Plugin:Test:testRequest" request="foo=bar"}{render action="TheliaSmarty\Tests\Template\Plugin:Test:testRequest" request="foo=baz" method="put"}

View File

@@ -0,0 +1,128 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace TheliaSmarty\Tests\Template;
use TheliaSmarty\Template\SmartyHelper;
/**
* Class SmartyHelperTest
* @package Thelia\Tests\Core\Smarty
* @author Julien Chanséaume <jchanseaume@openstudio.fr>
*/
class SmartyHelperTest extends \PHPUnit_Framework_TestCase
{
/**
* @var SmartyHelper
*/
protected static $smartyParserHelper;
public static function setUpBeforeClass()
{
self::$smartyParserHelper = new SmartyHelper();
}
public function testFunctionsDefinition()
{
$content = <<<EOT
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud {hook name="test"} exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
EOT;
$functions = self::$smartyParserHelper->getFunctionsDefinition($content);
$this->assertCount(1, $functions);
$this->assertArrayHasKey("name", $functions[0]);
$this->assertEquals("hook", $functions[0]["name"]);
$this->assertArrayHasKey("attributes", $functions[0]);
$this->assertArrayHasKey("name", $functions[0]["attributes"]);
$this->assertEquals("test", $functions[0]["attributes"]["name"]);
}
public function testfunctionsDefinitionVar()
{
$content = <<<'EOT'
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud {hook name=$test} exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore {function name="{$test}"} eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
EOT;
$functions = self::$smartyParserHelper->getFunctionsDefinition($content);
$this->assertCount(2, $functions);
$this->assertArrayHasKey("name", $functions[0]);
$this->assertEquals("hook", $functions[0]["name"]);
$this->assertArrayHasKey("attributes", $functions[0]);
$this->assertArrayHasKey("name", $functions[0]["attributes"]);
$this->assertEquals("\$test", $functions[0]["attributes"]["name"]);
$this->assertArrayHasKey("name", $functions[1]);
$this->assertEquals("function", $functions[1]["name"]);
$this->assertArrayHasKey("attributes", $functions[1]);
$this->assertArrayHasKey("name", $functions[1]["attributes"]);
$this->assertEquals("{\$test}", $functions[1]["attributes"]["name"]);
}
public function testfunctionsDefinitionInnerFunction()
{
$content = <<<'EOT'
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud {hook name={intl l="test"}} exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore {hook name={intl l="test"}} eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
EOT;
$functions = self::$smartyParserHelper->getFunctionsDefinition($content);
$this->assertCount(2, $functions);
for ($i = 0; $i <= 1; $i++) {
$this->assertArrayHasKey("name", $functions[$i]);
$this->assertEquals("hook", $functions[$i]["name"]);
$this->assertArrayHasKey("attributes", $functions[$i]);
$this->assertArrayHasKey("name", $functions[$i]["attributes"]);
$this->assertEquals("{intl l=\"test\"}", $functions[$i]["attributes"]["name"]);
}
}
public function testfunctionsDefinitionSpecificFunction()
{
$content = <<<'EOT'
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud {hook name="hello world" } exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore {function name={intl l="test"}} eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
EOT;
$functions = self::$smartyParserHelper->getFunctionsDefinition($content, array("hook"));
$this->assertCount(1, $functions);
$this->assertArrayHasKey("name", $functions[0]);
$this->assertEquals("hook", $functions[0]["name"]);
$this->assertArrayHasKey("attributes", $functions[0]);
$this->assertArrayHasKey("name", $functions[0]["attributes"]);
$this->assertEquals("hello world", $functions[0]["attributes"]["name"]);
}
}