All of the following testing was done on a production style ICS installation without `IN_DEV=true` or the developer toolset installed. It was just a naked ICS 4.5 installation with only my application installed as a third party application.
The hook in question:
//<?php
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
exit;
}
class ts3integration_hook_AppLogo extends _HOOK_CLASS_
{
/* !Hook Data - DO NOT REMOVE */
public static function hookData() {
return array_merge_recursive( array (
'appmenu' =>
array (
0 =>
array (
'selector' => '#acpAppList',
'type' => 'add_before',
'content' => '',
),
),
), parent::hookData() );
}
/* End Hook Data */
}
Note that it has no content in it.
The parser error I see is:
How I verified it was my hook
When i include this hook in my project, compile my project and install it on a fresh installation of IPS, I get a 500 error.
After a lot of debugging i've confirmed it is this hook that's causing the issue by filtering it out in the \IPS\Theme PHP file (./system/Theme/Theme.php).
if ($data['class'] != 'ts3integration_hook_AppLogo') {
$class = "IPS\\Theme\\" . $data['class'] . "_tmp";
$templateHooks = array_merge_recursive( $templateHooks, $class::hookData() );
}
When I wrap that code in an if statement filtering out my hook, the page loads just fine.
How I debugged further
I found the relevant code in Theme.php and updated it to print a lot of information.
try
{
if ( @eval( $compiledGroup ) === FALSE )
{
throw new \IPS\Theme\TemplateException( 'Invalid Template', 1000, NULL, array( 'group' => $group, 'app' => $app, 'location' => $location ), $this );
}
}
catch ( \ParseError $e )
{
header('Content-Type: text/plain;');
echo $app . '/' . $location . '/' . $group . PHP_EOL;
print_r($e);
echo $compiledGroup;
exit;
}
Which resulted in this
core/admin/global
ParseError Object
(
[message:protected] => syntax error, unexpected 'endforeach' (T_ENDFOREACH), expecting elseif (T_ELSEIF) or else (T_ELSE) or endif (T_ENDIF)
[string:Error:private] =>
[code:protected] => 0
[file:protected] => /var/www/html/system/Theme/Theme.php(854) : eval()'d code
[line:protected] => 238
[trace:Error:private] => Array
(
[0] => Array
(
[file] => /var/www/html/system/Dispatcher/Admin.php
[line] => 120
[function] => getTemplate
[class] => IPS\_Theme
[type] => ->
)
[1] => Array
(
[file] => /var/www/html/system/Dispatcher/Dispatcher.php
[line] => 109
[function] => init
[class] => IPS\Dispatcher\_Admin
[type] => ->
)
[2] => Array
(
[file] => /var/www/html/admin/index.php
[line] => 14
[function] => i
[class] => IPS\_Dispatcher
[type] => ::
)
)
[previous:Error:private] =>
)
// REMOVED LONG $compiledGroup OUTPUT
The $compiledGroup output was too long to display here, however I did discover which line was causing the issue by running it through a PHP syntax validator and found the unexpected `endforeach;`. You can see it on the last line of this block:
if ( $appAndModule . "_" . $key === $currentItem ):
$return .= <<<CONTENT
>
</ul>
</li>
CONTENT;
endforeach;
Conclusion
I don't understand how my hook above causes this issue. Especially since the unexpected endforeach; has nothing to do with my hook. To me this seems like a bug in ICS and not an issue with my application, but I can't tell for certain.