using TYPO3 core hooks only in one site of a multi site installation - typo3

i defined a hook in ext_localconf.php:
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typoLink_PostProc']['titleTagsInHiddenText'] = SNM\StmwiAccessibility\ExtendTypolink::class . '->convertTitleInHiddenText';
This hook will be executed on every link on the page, on all pages of all sites. This could be a performance killer ...
So, is there a possibility to restrict the use of the hook to the actual page? Is it possible to get the current site in ext_localconf.php?
e.g.:
$currentSite = ????;
if ($currentsite = 'rootPidOfMySite') {
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']
}
This question rises in other contexts too: i often want to restrict the performance consuming configuration of extensions to one single site. I can do it with the static setup file but not with the stuff in ext_localconf.php.
Thanks!

Which TYPO3 version do you use? There is an API to access the site configuration. I'd say you need to register PSR-15 middleware and then you can access the site configuration. More details can be found in the documentation.

Related

TYPO3 REST Extension setup

I'm trying to setup the REST-Extension v2 in TYPO3 8.7 following this tutorial. I included the 2 templates called Virtual-Object-Page and Virtual-Object-Content in my template. I made a new extension using Extension Builder 8.7 from Github with a simple model. I installed the new extension and made some Instances of my model in the List View on my start page. In the Typoscript of my template I added:
plugin.tx_rest.settings.paths {
1 {
path = me-kinder-child
read = allow
write = allow
}
}
Me is the Vendor, kinder my extension key and child is my model.
When I'm calling http://localhost/rest/ I get The requested URL /rest/ was not found on this server.
What am I missing?
The path in the setup is explained being possible with several options, so perhaps try different configuration, possible is also all.
I don't see a fault in your setup, so the fault might be related to the server-file .htaccess or the extension realurl respectively the combination of both perhaps.
If you try it already with realurl or cooluri then disable that to get it running without first.
The htaccess file you can disable first too and enable it later again to adjust all requirements to each other.
The problem was not about RealURL was missing in any way. I just did not clear a cache that got cleared while installing RealURL. I guess that the "Clear all caches"-button in the Install-Tool would do it too.

TYPO3: disable cache for specific plugin / extension

I built an extension and a plugin where frontend-users can edit their profile but I noticed a critical issue:
Under "Edit profile", users could see the full information about another user who wasn't even logged in. Apparently the form was a cached on the server because after adding:
config.no_cache = 1
it didn't happen again. Now the issue is that indexing is disable on the whole website.
Is there a way to disable caching only for this specific extension / plugin ?
You should have something like this in your ext_localconf.php :
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
$_EXTKEY,
'List',
array('User' => 'list,editProfil'),
array('User' => 'editProfil') // Uncached actions
);
Here is where it is explained : https://docs.typo3.org/typo3cms/ExtbaseFluidBook/4-FirstExtension/7-configuring-the-plugin.html
If you want this to only apply on specific pages or be controllable by integrators, you can override the TS rendering instruction for the object:
tt_content.list.20.YOURLISTTYPEHERE = USER_INT
Or if you registered it as a custom CType:
tt_content.YOURCTYPEHERE.20 = USER_INT
The above should work for fluid_styled_content and css_styled_content.
It is almost never advisable to use config.no_cache = 1 since this disables a lot of things other than just caching, as you found out. It also disables all caching for the entire page and it is almost always better for performance to only make the specific plugin not cacheable - and if possible, only do so on pages where the plugin gets used to render views which should not be cached.
Be careful if you do end up needing to cache some parts of your view. It isn't a silver bullet in terms of security, but it is a good start to always include the user's ID (and possibly other things from the authentication as well) in any cache identifiers. And try not to store sensitive information in caches at any point, including code where you output things like the user's name.

Consuming a rest api with Drupal

I am currently maintaining a drupal 7 site. Although I already gained some experience with Drupal my knowledge is still rather low-level and doesn't go beyond installing and configuring modules.
My site is pretty much a metadata repository. People fill in forms about datasets.
My problem is probably rather basic (or maybe not - it's hard to say).
I need to implement an external file repository. The data repository provides a REST API that should allow the users to upload files to their repository using my drupal site.
After uploading a file the data repository then provides a permanent identifier that I have to save in addition to the other fields.
Now I'm looking for the best way to build a very simple UI that allows users to upload their files to the repository without leaving my drupal site (e.g. while they are in the process of filling in the fields). I also need the liberty to form the URLs needed myself as commands for the API as there are many options that need to be declared. For instance I need to provide a certain token in my URLs for the data repository to be able to identify who's uploading.
I already did some research and found modules like:
https://www.drupal.org/project/wsclient
https://www.drupal.org/project/chr
https://www.drupal.org/project/rest_client
or these topics:
http://drupal.stackexchange.com/questions/42103/how-do-i-consume-rest-as-a-client
https://www.drupal.org/node/1114312
However, I still wasn't able to find out what the best strategy is to implement that.
What I need are tips on what the best way is to do that.
Currently I don't really know what I'm looking for.
Also I do realise that the are drupal forums where I could ask a question like this, but I have far more better experiences with stackoverflow.
I'd appreciate any help.
Thanks
Sorry for answering my own question, but based on the information I got from here:
https://drupal.stackexchange.com/questions/42103/how-do-i-consume-rest-as-a-client
I was able to solve the problem.
I wrote a custom drupal module that communicates with the API.
Drupal 7 comes with its own function for https requests:
https://api.drupal.org/api/drupal/includes%21common.inc/function/drupal_http_request/7.x
However, it wasn't enough for my needs as I also neeeded to transfer data, so I ended up using the php library curl (https://curl.haxx.se/), which was built for exactly that purpose.
Basically, you install curl on your server where your drupal installation is also running on. Somewhere in your custom module, preferably in a config menu, you can check if the installation was succesful using something like this:
function _is_curl_installed() {
if (in_array ('curl', get_loaded_extensions())) {
return true;
}
else {
return false;
}
}
if (_is_curl_installed()) {
drupal_set_message(t('Curl is installed.'));
} else {
drupal_set_message(t('Curl is NOT installed.'), 'error');
}
Drupal should be able to recognise curl automatically after the installation.
And here is one example for a rest call in drupal using curl (based on this answer how to upload file using curl with php). Keep in mind that the syntax using '#' is outdated and that drupal will complain about it. In my example I used "new CURLFile".
$request = curl_init($deposit_url);
curl_setopt($request, CURLOPT_POST, true);
$cfile = new CURLFile($file_realpath,'application/octet-stream', $base_file_name);
curl_setopt(
$request,
// the content of the array depends on the API you are communicating with
CURLOPT_POSTFIELDS,
array(
'file' => $cfile,
'access_token' => $temp_token,
'verify' => false,
));
curl_setopt($request, CURLOPT_RETURNTRANSFER, true);
$output= curl_exec($request);
// output the response
// drupal_set_message(t('The curl output [1] is '.$output));
curl_close($request);
I hope this is helpful to someone.
EDIT: I released a contributed module that solves the described problem:
https://www.drupal.org/project/b2share
Yes you can implement nice REST API services using Drupal if you are using drupal 7 try to use "Services" MOdule that would be a great starting point for your project by using this module you can create your own endpoinds and you can intergrate other applications to this endpoinds.

How to make development site Noindex Nofollow, but production without

I have a joomla 3.3 development site and a production site. I'm doing all development in the development site and every time that the development get pushed to production, I need to make sure I change noindex,nofollow to index, follow.
Anyway I can keep development noindex,nofollow without changing production?
There is an easier method than using noindex, nofollow. Use canonical links on your pages, using the production url. Like this, even if search engines find about your development pages, they won't index them.
Use a conditional php code inside the template head php file.
<?php
//if host is development show noindex
$host = $_SERVER['HTTP_HOST'];
if($host == "development.com")
{
echo "<meta name=\"robots\" content=\"noindex, nofollow\">";
}
?>
When you move the files to the production server you don't have to copy configuration.php that store the variable for robots in public $robots = '';.
I highly recommend you to keep your development installation htaccess password protected to be sure that would never be accessed by search engines.
Hope this helps

External access to Magento instances

I've started investigating alternatives to my project and a few questions came out that I couldn't answer by myself.
The problem is: I want to create a web page able to access multiple Magento instances installed in the same server. Currently, I have one Magento instance per client and this project will access several Magneto instances to export reports from each one (for example).
The alternatives I thought til this moment are:
Have another Magento instance, create a new module within it that changes its 'database target' before triggering operations/queries;
Questions until this moment:
Can I 'change the database target' of a Magento instance?
How can I access data from a Magento instance without appeal to SOAP/REST?
I want to re-use some components (grids, tabs, forms..) from Magento, that's why I'm not considering an independent project (Zend, for instance) that can access this code from another projects. Does it make sense?
Any other idea?
==Edited==
Thanks by the tips and sorry by my ignorance. The comments let me believe that I'm able to execute something like this:
// File myScript.php
require '/home/DOMAIN1/app/Mage.php';
Mage::app('default');
// get some products from DOMAIN1
require '/home/DOMAIN2/app/Mage.php';
Mage::app('default');
// get some products from DOMAIN2
Is it right? Can I execute require twice (and override things from first require)?
==Edited2==
I'm still trying to connect to several Magento instances from a single third party file. Is there any tip? I'm facing several/different errors at this moment.
The only thing I know is that I can still rely on SOAP to get the information I need, but this will be expensive.
Thanks!
The easiest way would be to include Mage.php from each shop instance. You would need to use namespaces or some other trickery to be able to load more then one.
Or if that doesn't work - make your own API in a separate file to get what you want from one shop, and combine the results in the PHP-file that calls the API.
Here's a sample on how to use Magento functionality outside of Magento:
require 'app/Mage.php';
if (!Mage::isInstalled()) {
echo "Application is not installed yet, please complete install wizard first.";
exit;
}
Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
// your custom code here, for example, get the product model..
$productModel = Mage::getModel('catalog/product');