I did an upgrade from typo3 4.5.0 to 6.2.14 and I get an issue with a custom extension which one of its functionality is to include custom plugins that are stored in extensions directory.
The plugins that are going to be included used the code below. The location of this code is in extensionkey/ext_tables.php
if (file_exists($path) && is_dir($path)) {
$files = scandir($path);
foreach ($files as $f) {
if (is_dir($path.$f) && $f!='.' && $f!='..' && $f!='.svn') {
$TCA['tt_content']['types']['list']['subtypes_excludelist'][$_EXTKEY.'_'.$f]='layout,select_key,pages';
$confArr = array('LLL:EXT:extensionkey/locallang_db.xml:tt_content.list_type_'.$f, $_EXTKEY.'_'.$f, '');
t3lib_extMgm::addPlugin($confArr,'list_type');
}
}
}
Please enable the "Development Mode" in the install tool, then you will see all errors. t3lib_extMgm::addPlugin does not exist in TYPO3 6.2 anymore and should result in an exception. It must be replaced with \TYPO3\CMS\Extbase\Utility\ExtensionManagementUtility
Related
I'm updating a project and I've decided to update my Twig version. I deliberately haven't updated it in the past because of the fact you now need to use Composer, but I've eventually given in to this and decided to install a newer version.
However, it's messing around with my Autoload functions and not loading Twig properly, and I really don't want to have to use it. In a blank file with only the code to autoload Composer it works, so I know my autoloader is clashing. I can see that I'm going to have to use it to some degree, because Twig now requires it. I'm only interested in using it for third-party code, and I don't want to use it for anything else. So what I'm looking for is my own autoloader to try first, and then if I can't load a class by my own means, to try using the Composer autoloader. Third-party code exists in a subdirectory of "Lib". So With Twig, it sits in Lib/vendor/twig/twig/src.
At the moment, I'm checking the first part of the namespace and if it isn't matching my own, I'm trying to load the Composer autoload.php file in Lib/vendor/autoload.php, and then returning back out of my autoload function. But this doesn't seem to be finding the class.
Is what I'm trying to do actually possible? How would I approach something like this?
** Edit - Current Autoloader **
public static function autoloader($classname)
{
/* Separate by namespace */
$bits = explode('\\', ltrim($classname, '\\'));
$vendor = array_shift($bits);
/* If this doesn't belong to us, ignore it */
if ($vendor !== 'Site')
{
// We don't want to interfere here
if ($vendor == 'Forum')
return;
// Try to see if we can autoload with Composer, if not abort
include_once(SITE_ROOT.'include/Lib/vendor/autoload.php');
print_r(spl_autoload_functions ( ));
return;
}
$class = array_pop($bits);
$namespace = empty($bits) ? 'Site' : ('Site\\'.implode('\\', $bits));
$sources_dir = false;
$path = SITE_ROOT.'include/';
foreach (array_merge($bits, array($class)) as $i => $bit)
{
if ($i === 0 && $bit == 'Lib')
{
$bit = mb_strtolower($bit);
$sources_dir = true;
}
else if (preg_match("/^[a-z0-9]/", $bit)) // Applications only contain lowercase letters
{
if ($i === 0)
$path .= 'apps/';
else
$sources_dir = true;
}
else if ($i === 1 && ($bit == 'Api' || $bit == 'Cli' || $bit == 'Ajax')) // The API/CLI/AJAX interfaces have slightly different rules ....
{
$bit = mb_strtolower($bit);
$sources_dir = true;
}
else if ($sources_dir === false)
{
if ($i === 0)
{
$path .= 'components/';
}
else if ($i === 1 && $bit === 'Application')
{
// Do nothing
}
else
{
$path .= 'sources/';
}
$sources_dir = true;
}
$path .= $bit.'/';
}
/* Load it */
$path = \substr($path, 0, -1).'.php';
if (!file_exists($path))
{
$path = \substr($path, 0, -4).\substr($path, \strrpos($path, '/'));
if (!file_exists($path))
{
return false;
}
}
require_once($path);
if (interface_exists("{$namespace}\\{$class}", FALSE))
{
return;
}
/* Doesn't exist? */
if (!class_exists("{$namespace}\\{$class}", FALSE))
{
trigger_error("Class {$classname} could not be loaded. Ensure it has been properly prefixed and is in the correct namespace.", E_USER_ERROR);
}
}
It might be too late to load Composer's autoload.php within the custom autoload.
You should not worry too much about performance issues and just load both your custom autoloader and Composer's autoload one after to other. You can optimize a little by prioritizing these autoloaders based on which classes will you load more often (your own or those installed via Composer).
Also, your own/custom autoloader should only care about successful loading and not throw errors if something is not found. Leave that to PHP, this could help with compatibility with other autoloaders.
I'm using rmdir() within PHP on Windows to recursively delete a folder structure. It deletes all the contents of the folder fine, but leaves the base folder in an "unaccessible" state. I still have to delete that folder manually, even though the system says it can't be found. Somehow the act of "deleting" reminds the OS that it needs to actually remove it.
Here's my code with sources commented in:
function rrmdir($dir)
{
// Taken from:
// https://stackoverflow.com/a/3338133/6674014
if(is_dir($dir))
{
$objects = scandir($dir);
foreach($objects as $object)
{
if($object != "." && $object != "..")
{
if(is_dir($dir."/".$object))
$this->rrmdir($dir."/".$object);
else
{
// Added modification from comment attached to:
// https://stackoverflow.com/a/12148318/6674014
$objPath = $dir.'/'.$object;
chmod($objPath, 999);
unlink($objPath);
}
}
}
rmdir($dir);
}
}
I've also used the $handle method, as well as the Folder Iterator Thing. These have also not worked.
And here's the error when I double-click the ghost folder:
How can this problem be fixed? Is it my code or OS that's messing up?
I have been working on a project that involves a step, during which the script needs to automatically remove a certain directory in Linux ( and all its contents ).
I am currently using the following code to do that:
# Perform a recursive removal of the obsolete folder
$dir_to_erase = $_SESSION['path'];
function removeDirectory($dir_to_erase) {
$files = glob($dir_to_erase . '/*');
foreach ($files as $file) {
is_dir($file) ? removeDirectory($file) : unlink($file);
}
rmdir($dir_to_erase);
return;
}
Where $_SESSION['path'] is the folder to erase. Been working like a charm, but I recently had to add a .htaccess file to the folder, and I noticed the script stopped working correctly ( it keeps removing the rest of the files fine, but not the .htaccess files ).
Can anyone point me as to what I should add to the code include the hidden dot files in the removal process?
simply, you can rely on DirectoryIterator
The DirectoryIterator class provides a simple interface for viewing
the contents of filesystem directories.
function removeDirectory($dir_to_erase) {
$files = new DirectoryIterator($dir_to_erase);
foreach ($files as $file) {
// check if not . or ..
if (!$file->isDot()) {
$file->isDir() ? removeDirectory($file->getPathname()) : unlink($file->getPathname());
}
}
rmdir($dir_to_erase);
return;
}
there are lot of features there you may make use of them, as check the owner which is pretty useful to make sure not to remove critical file.
You can slightly modify your function to remove hidden files also:
function removeDirectory($dir)
{
if (is_dir($dir)) {
$objects = scandir($dir);
foreach ($objects as $object) {
if ($object != "." && $object != "..") {
if (is_dir($dir."/".$object))
removeDirectory($dir."/".$object);
else
unlink($dir."/".$object);
}
}
rmdir($dir);
}
}
As per this answer:
PHP glob() doesnt find .htaccess
glob(".*") will find .htaccess
How do I from PHP code if a PECL extension is installed or not?
I want gracefully handle the case when an extension is not installed.
I think the normal way would be to use extension-loaded.
if (!extension_loaded('gd')) {
// If you want to try load the extension at runtime, use this code:
if (!dl('gd.so')) {
exit;
}
}
get_loaded_extensions fits the bill.
Use like this:
$ext_loaded = in_array('redis', get_loaded_extensions(), true);
Have you looked at get_extension_funcs?
Couple different ways. You can just check for the existence of the class, or even a function: class_exists, function_exists, and get_extension_funcs:
<?php
if( class_exists( '\Memcached' ) ) {
// Memcached class is installed
}
// I cant think of an example for `function_exists`, but same idea as above
if( get_extension_funcs( 'memcached' ) === false ) {
// Memcached isn't installed
}
You can also get super complicated, and use ReflectionExtension. When you construct it, it will throw a ReflectionException. If it doesnt throw an exception, you can test for other things about the extension (like the version).
<?php
try {
$extension = new \ReflectionExtension( 'memcached' );
} catch( \ReflectionException $e ) {
// Extension Not loaded
}
if( $extension->getVersion() < 2 ) {
// Extension is at least version 2
} else {
// Extension is only version 1
}
I'm trying to write some code to track dependencies. Is there a way to programatically detect if a PEAR package has been installed? I'm thinking something like:
if ($some_pear_api->isPackageInstalled('FooPack')) {
echo 'FooPack is installed!';
} else {
echo 'FooPack is not installed. :(';
}
I know you can simply detect if the class file for that package exists, but I mostly want to know if PEAR has that installed because sometimes some libraries provide other means of including their code (e.g. PHPUnit has a pear channel as well as a git repo.).
Thanks for the help!
You need to use the PEAR_Registry class to do this (which is what the PEAR script itself uses).
Read Adam Harvey's blog post "pear -> list" from 3 years ago - all the details/examples you need are there.
include 'PEAR/Registry.php';
$reg = new PEAR_Registry;
foreach ($reg->listPackages() as $package) {
print "$package\n";
}
If you need this to check for specific versions of each package, then you could base something on the following example, which I provided in a comment to that blog entry:
<?php
require 'PEAR/Registry.php';
$reg = new PEAR_Registry;
define("NAME", 0);
define("VERSION", 1);
$packages = array(
array("PEAR", "1.6.2"),
array("Date", "1.4.7"),
array("Date_Holidays", "0.17.1"),
array("Validate_IE", "0.3.1")
);
foreach ($packages as $package) {
$pkg = $reg->getPackage($package[NAME]);
$version = $pkg->getVersion();
echo "{$package[NAME]} – {$package[VERSION]} – ";
echo version_compare($version, $package[VERSION], '>=') ? 'OK': 'BAD', "\n";
}
?>
If you need to copy and paste this, then it might be best for you to use the version at https://gist.github.com/kenguest/1671361.
You can use Pear/Infos packageInstalled to answer this:
<?php
require_once 'PEAR/Info.php';
$res = PEAR_Info::packageInstalled('FooPack');
if ($res) {
print "Package FooPack is installed \n";
} else {
print "Package FooPack is not yet installed \n";
}
?>
Why not just include the package and see if the class exists?
// Supress Errors. Checking is done below.
#require_once 'PHP/UML.php';
if(!class_exists('PHP_UML'))
{
throw new Exception('PHP_UML is not installed. Please call `pear install PHP_UML` from the command line',1);
}
// Code to use PHP_UML below...
$uml = new PHP_UML();