composer and site configuration files - composer-php

Is it possible to install a file out of the 'vendor' directory when doing a composer install/update?
Let me elaborate a bit more if your not sure what i mean.
I have a config file(s) that are stored in /config/ini/<filename>.ini and lots of vendor modules in the vendor directory. Would it be possible to package the ini files with the vendor packages so upon installation they are written to the correct directory?
Ideally I need to be able to achieve this because i have an Authentication vendor module that will need to be installed in various different applications. Being able to do this will mean that the private key and other shared configuration options can be stored with the vendor module (in a private repo ofc).
Thanks Mike

Yes, you can. You need to create a script which is attached to post-install-cmd or post-update-cmd. That script will look in the package directories, select the issues and dump them in the correct dir.
It'll be somewhere around these lines:
use Composer\Script\CommandEvent;
class ScriptHandler
{
public function bundleConfigs(CommandEvent $event)
{
$homeDir = $event->getComposer()->getConfig()->get('home');
$vendorDir = $event->getComposer()->getConfig()->get('vendor-dir');
$files = glob($vendorDir, '/*Module/config/*.ini');
foreach ($files as $file) {
copy($file, $homeDir.'/config/ini/'.basename($file));
}
}
}

Related

Switch to composer mode in running instance

How can I switch an existing project easily to composer? This project is updated from 6.1 to 8.7 now and should run in composer. A fresh composer setup is not a problem. For the last project I created a new host, installed TYPO3 via composer, installed the extensions via composer and migrated the db, fileadmin and uploads. Is there an easier way?
Migrating TYPO3 from Classic Mode to Composer Mode requires at least the following steps:
Write down the current version of TYPO3 and all extensions
Remove all embedded TYPO3 and extension code incl. Git submodules
Add a Composer manifest
Add the Composer vendor-dir (and bin-dir if custom) to your .gitignore
Require TYPO3 and all extensions with the versions and --prefer-lowest, e.g.
composer require typo3/cms:^8.7.7 --prefer-lowest
This ensures that you don't accidentally perform updates before completing the switch.
Since no further changes to user files or database data is required you will be running TYPO3 in Composer Mode now.
Afterward you will most likely also need to adapt your deployment workflow to ensure at least one composer install is executed after deploying a new version.
There is no real other way, at least no automatic way, as you also upgrade maybe to newer versions or sometimes to the exact same version
This is now documented in the "Installation and Upgrade Guide": https://docs.typo3.org/m/typo3/guide-installation/master/en-us/MigrateToComposer/Index.html
The steps are already outlined in the accepted answer.
As an alternative, you might want to create an installation from scratch with Composer and then use the generated composer.json for your system.
It generally makes sense to have your docroot in a subdirectory before you start so you have, for example:
/var/www/mysite (here, the composer.json will be created)
└──public/
├── fileadmin
├── typo3
└── typo3_src
You can have a look at my extension migrate2composer. However, this will only take care of creating the composer.json file. You have to take care of the rest of the steps yourself.
What it basically does is:
generated a list of all extension with the existing version
dump a sample composer.json file
If you want to do this yourself in your source code, you can take a look at TYPO3\CMS\Core\Package\PackageManager. This worked for TYPO3 v9 and v10 but may change in later versions:
public function getInstalledPackages(string $versionConstraintType = self::VERSION_CONSTRAINT_CARET) : array
{
$packagesInfo = [];
$this->errors = [];
$this->setVersionConstraintType($versionConstraintType);
// collect information about active extensions
$packages = $this->packageManager->getAvailablePackages();
foreach ($packages as $package) {
$key = $package->getPackageKey();
if (!$this->packageManager->isPackageActive($key)) {
// ignore inactive packages
continue;
}
if ($package->getValueFromComposerManifest('type') === 'typo3-cms-framework') {
$type = 'system';
} else {
$type = 'local';
}
$name = $package->getValueFromComposerManifest('name');
// ....
By now the procedure for migrating to Composer is well documented in the official documentation.
Additional steps you must perform yourself:
mv public/typo3conf/sites config/sites
mv public/typo3conf/l10n var/labels
I have tried to generate a composer.json file from the PackageState.php successfully for a docker instance.
I loop through the PackageState.php, then parse each extension for its version and generate a composer.json from this aggregated information.
This is my script:
https://github.com/geri777/typo3-composerize

Writing the relative path in controller

While uploading image i have this path:
public function uploadImage()
{
$target_dir = 'C:\xampp\htdocs\application\public\newuploads';
...
It worked fine.
But, when i uploaded to production server i change it to:
$target_dir = 'www.mywebsite.com\public\newuploads';
It gives me error:
move_uploaded_file(www.mywebsite.com\public\newuploads/1487912832.
jpg): failed to open stream: No such file or directory
How can i write the relative path instead?
You should never hardcode the path. Use public_path() helper to get path to the public directory:
public_path('newuploads')
Never use any static path for local or live server.
Laravel provides lot of functions to do this:
Just use it like:
$target_dir = public_path()."/newuploads";
Use the same on local and live environment.
This will work.
For More Details And Laravel Helper Functions You Can Check This:
https://laravel.com/docs/5.4/helpers
Thanks
Depending on your production server, you may have a different root directory. That being said, instead of using a full folder path, you can use the public path root such as
$target_dir = '/newuploads';
That way if the underlying OS and file system changes, your site operations are intact.

Where should Puppet Resources be Placed?

I have the following flyway.pp Puppet class which installs Flyway onto Windows machines. It copies two files into the installation folder.
class rehan::flyway {
package { 'flyway':
ensure => latest,
provider => chocolatey
}
file { 'C:/Program Files/flyway/ntlmauth.dll':
ensure => 'file',
source => 'puppet:///modules/rehan/manifests/ntlmauth.dll',
}
file { 'C:/Program Files/flyway/drivers/sqljdbc4.jar':
ensure => 'file',
source => 'puppet:///modules/rehan/manifests/sqljdbc4.jar',
}
}
The above modules lives at modules/rehan/manifests/flyway.pp. I have placed the two files ntlmauth.dll and sqljdbc4.jar along side it but it seems a bit messy. Is there a standard directory or location where these files are normally placed? Also, how can I refer to these files using a relative path, I use puppet:///modules/rehan/manifests/ntlmauth.dll because I've seen it somewhere but that does not work.
This could be a bit confusing.
In your module's directory, you should have a subdirectory named 'files' and all files you want to be copied/installed somewhere need to be put there.
The confusing bit is that when addressing one of the objects stored there, you don't mention 'files' in the path!
So,
source => 'puppet:///modules/rehan/sqljdbc4.jar'
picks up the jar file from the following path:
/etc/puppet/modules/rehan/files/sqljdbc4.jar
The reason why puppet:///modules/rehan/manifests/ntlmauth.dll doesn't work is that it maps the path to /etc/puppet/modules/rehan/files/manifests/ntlmauth.dll which doesn't exist.
You can not reference an object located in your manifests directory using puppet:///

Manual installation of Magento extension turns every file into a folder

I am completely baffled by this. I packaged up an extension and manually installed it on a fresh Magento instance. (Both the packaging and installing machine were running Magento 1.7). The installation went smoothly, except every single file I installed was turned into a folder, named after the file. Every single file. Has anyone run into this? Could it be a Magento bug?
I used to see this problem when I manually created a tar archive to use as a Magento Connect archive. Unfortunately, I don't have a solution, but here's what I understand about the problem.
While Magento Connect tgz packages are technically gzip compressed tar archives — the code that creates and extracts these archives in not the standard *nix tar tool. Instead, Magento implemented its own packing and unpacking tar code for Magento Connect
downloader/lib/Mage/Archive/Tar.php
Unfortunately, this packing and unpacking code hasn't been robustly tested across operating systems or against tar archives created with standard *nix tools. My problem with this code was archives created on my Mac OS system via tar wouldn't unpack correctly with Magento Connect's code on a system running linux.
Hard to track down, hard to report, hard to reproduce means hard to fix.
These directories are being created when Magento Connect unpacks the tgz file. I'm be 99% sure your directories are being created by this bit of code
#File: downloader/lib/Mage/Archive/Tar.php
if (in_array($header['type'], array("0",chr(0), ''))) {
if(!file_exists($dirname)) {
$mkdirResult = #mkdir($dirname, 0777, true);
if (false === $mkdirResult) {
throw new Mage_Exception('Failed to create directory ' . $dirname);
}
}
$this->_extractAndWriteFile($header, $currentFile);
$list[] = $currentFile;
} elseif ($header['type'] == '5') {
if(!file_exists($dirname)) {
$mkdirResult = #mkdir($currentFile, $header['mode'], true);
if (false === $mkdirResult) {
throw new Mage_Exception('Failed to create directory ' . $currentFile);
}
}
$list[] = $currentFile . DS;
These are the two locations where Magento unpacks the archives and creates a folder. For some reason, there's a certain condition on your two systems where the data is being packed, or unpacked, incorrectly in/out of the archive file. Try un-archiving the tgz file manually with a command line tool or your operating system's built in un-archive program. If weird things happen then at least you know it's the packing code that's the problem.
It's definitely a bug, and while I'd report it, the only "solution" would be to not create your archive on your local machine (which I realize is an awful solution, but Ours is not to question why and all that)
This is a bug that has been present since 1.7, due to an if comparison never evaluating to false when reading the #././LongLink header. I answered it more on this question:
https://magento.stackexchange.com/questions/5585/long-file-names-and-magento-connect-extension-packager/45187#45187
I found that issue happening when packing a Magento Extension on OS X that is linked (modman) into magento folders. Folder creation only occured on Windows systems.
Might that happen here too?
Rico
I encountered it, when for some reason my plugin file was set with suffix .gz
so it was plugin.tgz.gz
unzip it to plugin.tgz solved my issue
I think the issue is because of PHP version. I faced the same issue while installing extension on Magento 1.8.1 , but I found a fix by changing _getFormatParseHeader() function in /downloader/lib/Mage/Archive/Tar.php file.
Originally the function was :
protected static final function _getFormatParseHeader()
{
return 'a100name/a8mode/a8uid/a8gid/a12size/a12mtime/a8checksum/a1type/a100symlink/a6magic/a2version/'
. 'a32uname/a32gname/a8devmajor/a8devminor/a155prefix/a12closer';
}
I changed it to :
protected static final function _getFormatParseHeader()
{
if (version_compare(phpversion(), '5.5.0', '<') === true) {
return 'a100name/a8mode/a8uid/a8gid/a12size/a12mtime/a8checksum/a1type/a100symlink/a6magic/a2version/'
. 'a32uname/a32gname/a8devmajor/a8devminor/a155prefix/a12closer';
}
return 'Z100name/Z8mode/Z8uid/Z8gid/Z12size/Z12mtime/Z8checksum/Z1type/Z100symlink/Z6magic/Z2version/'
. 'Z32uname/Z32gname/Z8devmajor/Z8devminor/Z155prefix/Z12closer';
}
Really nasty bug.
For me it renaming my manually packed file from *.tar.gz to *.tgz solved it.
At least it worked on my ubuntu 15.04
Tested with magento 1.8
it's more likely that you choose the wrong path when adding content to your extension.
For me the bug happened when I added (non existing) files from layout/base instead from layout/base/default.

Changing cache_dir and log_dir with Symfony2

Because of deployment constraints, I would like to have the log and cache directories used by my Symfony2 application somewhere under /var/... in my file system. For this reason, I am looking for a way to configure Symfony and to override the default location for these two directories.
I have seen the kernel.cache_dir and kernel.log_dir and read the class Kernel.php. From what I have seen, I don't think that it is possible to change the dir locations by configuration and I would have to patch the Kernel.php class.
Is that true, or is there a way to achieve what I want without modifying the framework code?
Add the following methods to app/AppKernel.php (AppKernel extends Kernel) making them return your preferred paths:
public function getCacheDir()
{
return $this->rootDir . '/my_cache/' . $this->environment;
}
public function getLogDir()
{
return $this->rootDir . '/my_logs';
}
I was happy to find your post, but I was a little bit confused of the unhelping answers.
I got the same problem and found out that the logs are depending on the config parameter
kernel.logs_dir.
So I just added it to my config.yml parameters:
kernel.logs_dir: /var/log/symfonyLogs
I hope it will helpfull for you even, if its a late answer.
i think the easiest way is to link the folder to another place. We have made this on the prod server but when you develop local perhaps on windows its a bit complicated to set the symlinks.
ln -s /var/cache/ /var/www/project/app/cache
something like this.
I would like to offer an alternative and that is to set environment variables to change these directories. This way it's easier to set depending on the stage. (testing, production or development)
export SYMFONY__KERNEL__CACHE_DIR "/your/directory/cache"
export SYMFONY__KERNEL__LOGS_DIR "/your/directory/logs"
Environment variables can also be set in the virtual host with SetEnv.
When reading kernel parameters symfony will look for all the $_SERVER variables that start with SYMFONY__, strip the first part and convert all the double underscores into a .
Source code
See line 568 to 608
In symfony you can override the cache (and logs) directory by extending the method in AppKernel.
// app/appKernel.php
class AppKernel extends Kernel
{
// ...
public function getCacheDir()
{
return $this->rootDir.'/'.$this->environment.'/cache';
}
}
Check out http://symfony.com/doc/current/cookbook/configuration/override_dir_structure.html#override-cache-dir
I used the configuration solution from Dragnic but I put the paths in the parameters.yml file because this file is ignored by git. in other words, it's not synchronized from my PC to the git repository so there is no impact in the prod environment.
# app/config/parameters.yml
parameters:
database_driver: pdo_mysql
[...]
kernel.cache_dir: "T:/project/cache"
kernel.logs_dir: "T:/project/logs"
Configuration: Windows7, WAMP 2.4 and Symfony 2.3.20.
But you have to know that:
Overwriting the kernel.cache_dir parameter from your config file is a very bad idea, and not a supported way to change the cache folder in Symfony.
It breaks things because you would now have different cache folders for the kernel Kernel::getCacheDir() and for the parameter.
Source: https://github.com/symfony/AsseticBundle/issues/370
So you should use it only in dev environment and if you don't want to change the content of the app/AppKernel.php file, otherwise see the other answers.
No accepted answer, and a really old question, but I found it with google, so I post here a more recent way to change the cache directory, and the logs directory, (source here)
remember, short syntax for arrays require php 5.4
you can select the env to modify, and manage different cache and logs directories if you want
public function getCacheDir()
{
if (in_array($this->environment, ['prod', 'test'])) {
return '/tmp/cache/' . $this->environment;
}
return parent::getCacheDir();
}
public function getLogDir()
{
if (in_array($this->environment, ['prod', 'test'])) {
return '/var/log/symfony/logs';
}
return parent::getLogDir();
}

Resources