xref: /dokuwiki/_test/tests/Parsing/HandlerTest.php (revision 36ba8eadc205a4e1af5099c74b747e2256faadd4)
171096e46SAndreas Gohr<?php
271096e46SAndreas Gohr
371096e46SAndreas Gohrnamespace dokuwiki\test\Parsing;
471096e46SAndreas Gohr
571096e46SAndreas Gohruse dokuwiki\Parsing\Handler;
671096e46SAndreas Gohruse dokuwiki\Parsing\ParserMode\ModeInterface;
771096e46SAndreas Gohr
871096e46SAndreas Gohrclass HandlerTest extends \DokuWikiTest
971096e46SAndreas Gohr{
1071096e46SAndreas Gohr    function testGetModeNameReturnsOriginalName()
1171096e46SAndreas Gohr    {
1271096e46SAndreas Gohr        $handler = new Handler();
1371096e46SAndreas Gohr
1471096e46SAndreas Gohr        // create a simple mode that records what getModeName() returns
1571096e46SAndreas Gohr        $mode = new class extends \dokuwiki\Parsing\ParserMode\AbstractMode {
1671096e46SAndreas Gohr            public $receivedModeName = '';
1771096e46SAndreas Gohr            public function getSort() { return 0; }
1871096e46SAndreas Gohr            public function handle($match, $state, $pos, Handler $handler)
1971096e46SAndreas Gohr            {
2071096e46SAndreas Gohr                $this->receivedModeName = $handler->getModeName();
2171096e46SAndreas Gohr                return true;
2271096e46SAndreas Gohr            }
2371096e46SAndreas Gohr        };
2471096e46SAndreas Gohr
2571096e46SAndreas Gohr        $handler->registerModeObject('resolved', $mode);
2671096e46SAndreas Gohr
2771096e46SAndreas Gohr        // simulate dispatch with a remapped name (original differs from resolved)
2871096e46SAndreas Gohr        $handler->handleToken('resolved', 'test', DOKU_LEXER_SPECIAL, 0, 'original');
2971096e46SAndreas Gohr
3071096e46SAndreas Gohr        $this->assertSame('original', $mode->receivedModeName);
3171096e46SAndreas Gohr    }
3271096e46SAndreas Gohr
3371096e46SAndreas Gohr    function testGetModeNameFallsBackToModeName()
3471096e46SAndreas Gohr    {
3571096e46SAndreas Gohr        $handler = new Handler();
3671096e46SAndreas Gohr
3771096e46SAndreas Gohr        $mode = new class extends \dokuwiki\Parsing\ParserMode\AbstractMode {
3871096e46SAndreas Gohr            public $receivedModeName = '';
3971096e46SAndreas Gohr            public function getSort() { return 0; }
4071096e46SAndreas Gohr            public function handle($match, $state, $pos, Handler $handler)
4171096e46SAndreas Gohr            {
4271096e46SAndreas Gohr                $this->receivedModeName = $handler->getModeName();
4371096e46SAndreas Gohr                return true;
4471096e46SAndreas Gohr            }
4571096e46SAndreas Gohr        };
4671096e46SAndreas Gohr
4771096e46SAndreas Gohr        $handler->registerModeObject('mymode', $mode);
4871096e46SAndreas Gohr
4971096e46SAndreas Gohr        // no original name passed — should fall back to the resolved name
5071096e46SAndreas Gohr        $handler->handleToken('mymode', 'test', DOKU_LEXER_SPECIAL, 0);
5171096e46SAndreas Gohr
5271096e46SAndreas Gohr        $this->assertSame('mymode', $mode->receivedModeName);
5371096e46SAndreas Gohr    }
54*36ba8eadSAndreas Gohr
55*36ba8eadSAndreas Gohr    /**
56*36ba8eadSAndreas Gohr     * Regression test for #4637
57*36ba8eadSAndreas Gohr     *
58*36ba8eadSAndreas Gohr     * handleToken() must route plugin_* modes through plugin() even when
59*36ba8eadSAndreas Gohr     * the same name is also registered as a mode object.
60*36ba8eadSAndreas Gohr     *
61*36ba8eadSAndreas Gohr     * Before the fix, modeObjects was consulted first, which called
62*36ba8eadSAndreas Gohr     * SyntaxPlugin::handle() directly. That returns data but never
63*36ba8eadSAndreas Gohr     * emits an instruction via addPluginCall(), so the plugin's rendered
64*36ba8eadSAndreas Gohr     * output silently disappeared.
65*36ba8eadSAndreas Gohr     */
66*36ba8eadSAndreas Gohr    function testPluginModeIsRoutedThroughPluginHandler()
67*36ba8eadSAndreas Gohr    {
68*36ba8eadSAndreas Gohr        $handler = new Handler();
69*36ba8eadSAndreas Gohr
70*36ba8eadSAndreas Gohr        // Plugins register themselves as mode objects under their plugin_* name.
71*36ba8eadSAndreas Gohr        // This reproduces the conflict the bug depended on.
72*36ba8eadSAndreas Gohr        $info = plugin_load('syntax', 'info');
73*36ba8eadSAndreas Gohr        $this->assertNotNull($info, 'info plugin must be available for this test');
74*36ba8eadSAndreas Gohr        $handler->registerModeObject('plugin_info', $info);
75*36ba8eadSAndreas Gohr
76*36ba8eadSAndreas Gohr        $handler->handleToken('plugin_info', '~~INFO:datetime~~', DOKU_LEXER_SPECIAL, 0);
77*36ba8eadSAndreas Gohr
78*36ba8eadSAndreas Gohr        // After the fix, plugin() runs and emits a plugin instruction.
79*36ba8eadSAndreas Gohr        // With the bug, modeObjects['plugin_info']->handle() ran and emitted nothing.
80*36ba8eadSAndreas Gohr        $this->assertCount(1, $handler->calls, 'plugin mode must emit exactly one instruction');
81*36ba8eadSAndreas Gohr        [$name, $args] = $handler->calls[0];
82*36ba8eadSAndreas Gohr        $this->assertSame('plugin', $name);
83*36ba8eadSAndreas Gohr        $this->assertSame('info', $args[0]);
84*36ba8eadSAndreas Gohr        $this->assertSame(['datetime'], $args[1]);
85*36ba8eadSAndreas Gohr        $this->assertSame('~~INFO:datetime~~', $args[3]);
86*36ba8eadSAndreas Gohr    }
8771096e46SAndreas Gohr}
88