Consuming a rest api with Drupal - rest

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.

Related

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

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.

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');

ZF2 Album tutorial using stored procedures

Please also suggest which namespace to use. I am new to zend and MVC.
module.php
public function getServiceConfig()
{
// what code here?
}
**Album\Model\Album.php**
{
//what code here?
}
**Album\Model\AlbumTable.php**
{
//what code here?
//do we have to use this class or a different class?
}
I can understand the sudden confusion when starting out with ZF2. However, the manual has really done a good job at helping those who are just starting out. You can find the most up-to-date information here : http://zf2.readthedocs.org/en/latest/user-guide/overview.html
Once you've got the Skeleton Application working I believe some of your confusion will be relieved. If not, come back and ask more specific questions OR you could even join the FreeNode IRC channel at #zftalk.
But to also help answer some of what you've asked here:
getServiceConfig() is where you will interact with the ServiceManager. Try to stay away from closures and work with Factories.
Album.php is sort of like the Hydrator. You don't have to use a Hydrator but for example purposes it was put here. It can make like easier in the long run.
AlbumTable.php is the Database Table you will be interacting with.
The namespace which is used in the tutorial is called Album. The Skeleton application comes packaged with a namespace called Application to start with.
You can manually download ZF2 here: https://packages.zendframework.com/
The latest skeleton application can be found here: https://github.com/zendframework/ZendSkeletonApplication
You may also choose to use Composer to install your entire application which tends to make the installation process much easier for those just starting out, so in your situation I'm going to recommend you use that. You can find instructions on how to use Composer here: http://zf2.readthedocs.org/en/latest/user-guide/skeleton-application.html

Collecting GitHub project issues statistics programmatically?

I'm collecting GitHub issue statistics over time on our project: total number of issues, number of issues with a particular label, number of issues in a given state (open/closed). Right now, I have a Python script to parse the project webpage with the desired labeling/state for the info I want, e.g., http://github.com/<projectname>/issues?label=<label_of_interest>&state=<state_of_interest>
However, parsing the HTML is fragile since if the GitHub API changes, more often than not, my code fails.
Does someone describe how to use the GitHub API (or barring that, know of some other way, preferably in Python) to collect these statistics without relying on the underlying HTML?
May I be so forward as to suggest that you use my wrapper around the GitHub API for this? With github3.py, you can do the following:
import github3
github = github3.login("braymp", "braymp's super secret password")
repo = github.repository("owner", "reponame")
open_issues = [i for i in repo.iter_issues()]
closed_issues = [i for i in repo.iter_issues(state='closed')]
A call to refresh may be necessary because I don't honestly recall if GitHub sends all of the issue information upon the iteration like that (e.g., replace i.refresh() for i in <generator> as the body of the list comprehensions above).
With those, you can iterate over the two lists and you will be able to use the labels attribute on each issue to figure out which labels are on an issue. If you decide to merge the two lists, you can always check the status of the issue with the is_closed method.
I suspect the actual statistics you can do yourself. :)
The documentation for github3.py can be found on ReadTheDocs and you'll be particularly interested in Issue and Repository objects.
You can also ask further questions about github3.py by adding the tag for it in your StackOverflow question.
Cheers!
I'd take a look at Octokit. Which doesn't support Python currently, but does provide a supported interface to the GitHub API for Ruby.
https://github.com/blog/1517-introducing-octokit
Although this doesn't fully meet your specifications (the "preferably Python" part), Octokit is a fantastic (and official - it's developed by GitHub) way of interacting with the GitHub API. You wrote you'd like to get Issues data. It's as easy as installing, requiring the library, and getting the data (no need for authentication if the project is public).
Install:
gem install octokit
Add this to your Ruby file to require the Octokit library:
require 'octokit'
Although there are a lot of things you can get from Octokit::Client::Issues, you may want to get a paginated list of all the issues in a repository:
Octokit.list_issues('octokit/octokit.rb')
# => [Array<Sawyer::Resource>] A list of issues for a repository.
If you're really keen on using Python, you might want to have a look at the GitHub API docs for Issues. Really, it's as easy as getting a URL like: https://api.github.com/repos/octokit/octokit.rb/issues and get the JSON data (although I'm not familiar with Python, I'm sure these some JSON parsing library); no need for authentication for public repos.

Accessing a sharepoint using perl and webdav

a similar question was asked in question 494120, but IMHO was not really answered...
I want to upload files to a sharepoint using perl/WebDAV (from a Win32 host). To achive this, I need to authenticate with KERBEROS on the server. After googling for hours and trying different approaches, I'm not able to open a connection. Current code is this:
my $agent = HTTP::DAV::UserAgent->new(keep_alive=>1);
$agent->agent('Agent');
$agent->timeout(1000);
my $d = HTTP::DAV->new(-useragent => $agent);
$d->credentials( -user=>$user,-pass =>$pass, -url =>$url);
$d->open( -url=>$url ) or die("Couldn't open $url: " .$d->message . "\n");
When doing the $d->open(...), I always get "Couldn't open $url: Unauthorized. Negotiate". So, obviously the basic authentication doesn't work.
Could anyone point me to the right path, please? I am not fixed to using WebDAV, any other mechanism would fit me as well. Just want to get it working...
Edit 1
When using LWP along with Authen::NTLM (as suggested by Madhur) also doesn't work. It results in a 500 internal server error on IIS as well as on Apache. Since the same error occurs on two different web servers (with two different NTLM implementations) I guess that there's gotta be a problem in the Authen::NTLM module.
Looking at the implementation of Authen::NTLM it seems to me that the code is kinda reverse engineered and neither implemented based on a specification nor is it really configurable. What turns up the question why the specification wasn't used to implement the module...
Is using NTLM along with Perl such an exotic use case?
Edit 2
Based on Madhur's suggestion, I tried accessing the Sharepoint with Curl. This works. But sniffing the NTLM messages of Curl and those sent by Perl shows me, that the message format is somehow different.
Instead of using WebDAV. I would suggest you use out of the box web services.
This gives overview on how to use sharepoint web services in PERL:
http://www.squish.net/log/2008/10/11/perl-sharepoint/
http://shareperl.blogspot.com/
And this is the .NET code to upload the file using web service:
http://www.oriolardevol.com/Article/Details/3
Converting it to PERL code is left to you as its been years since I used PERL :)