Giter VIP home page Giter VIP logo

wsdata's Introduction

About

Web Service Data is a collection of modules allowing you to interact with web services using entities and fields in Drupal.

Modules/Sub-Modules

Web Service Data (wsdata)

  • Defines abstract classes for Web Service Connectors (WsConnector) and Web Service Data Processors (WsData).

Web Service Configuration (wsconfig)

  • Defines an entity type called "wsconfig_type" which stores information about how the URL to the root of a web service and which connector type to use (ex: RESTClient for REST based services).

  • Defines an entity called "wsconfig" which stores information about how to interact with a given service (ex: /service/user) and each of the CRUD operations.

Web Service Fields Storage (wsfields_storage)

  • Defines a field storage controller which uses the CRUD operations defined in a wsconfig to interact with remote data using Drupal Fields.

Caveat. Since the field module caches loaded field data, you should use the provided cache backend for fields. You can do this by adding the following to your settings.php file, updated to reflect the location of wsfields_storage:

$conf['cache_backends'][] = 'sites/all/modules/wsdata/modules/wsfields_storage/wsfields_storage.cache.inc';

Web Service Fields (wsfields)

  • Contains implementations of the core fields to parse data coming from an implementation of "WsData" into the proper format expected by each field type.

Web Service Beans (wsbeans)

  • Adds a bean type called "wsbean" which is a bean that will render the results of a web service call.

Web Service Hybrid Fields (wshybridfield)

Adds a new field type "WS Hybrid Field". This field contains web service connection info, and the web service is result is rendered when the field is displayed. This field should be used when it is ony desired that extra remote data should be displayed when a entity is viewed.

It cannot afford any of the integration available with wsfields and wsfields_storage, however the use and configuration is more straight forward.

Web Service Solr Integration (wsdata_solr)

Provides default processors for parsing JSON data returned by solr queries.

Web Service Entities (wsentities)

Not Yet Implemented

Web Service Services (ws_services)

  • Sample implementation on connecting to web services of another Drupal site which is sharing data using the Services module.

  • Includes a test suite for the wsdata module as a whole

Web Service Fields - Address Field (ws_addressfield)

Web Service Fields - Date Field (ws_datefield)

Web Service Fields - Entity Reference Field (ws_entityreferencefield)

Installation

  1. Download all dependencies
  2. Enable the module

Usage

Preface

You need to determine two key factors:

  1. What web service request method are you using (ex: SOAP, REST)
  2. What data formats do your web services accept/reply (ex: XML, JSON, text)

Prerequisites

  • Compatible 'Connector' module

    • You'll need a means of making the web service requests. A module which implements hook_wsconfig_connector_info() and an implementation of WsConnector which is compatible with your request method.
  • Processor classes

    • For each web service, you'll need to implement and instance of WsData to parse the returned values into values compatible with Drupal. Typically, after writing a few you'll notice some patterns and be able to reuse significant portions of your code.

Implementation

For details on how to implement each individual API, please see their accompanying README.txt files. (ex: see wsdata/modules/wsfields_storage/README.txt on how to define fields to use the storage controller)

Example Implementations

See 'ws_services' module for an example implementation.

Connectors

You can use the RESTClient module connector as a sample to build your connectors with.

Processors

See wsdata/modules/ws_services/includes for a list of sample implementations of WsData.

History

Below is an explanation of how and why wsdata came into existence and the types of solutions it can provide to developers working with Drupal and web services.

The Problem

Drupal gives developers and site builders a lot of power in its Entity and Field APIs. However, the default implementations assume that all your data exists within Drupal's tables; that Drupal is the primary data source.

When dealing with enterprises with a historical data set, it isn't always feasible or practical to migrate and/or copy this data into Drupal.

In these cases you have two options; build "dumb views" on the data. To display it to the user or expose it to parts of Drupal you write custom code to load the information from the service into custom tables or as temporarily cached data. But you lose all of the power and flexibility of having the data exist as entities/fields.

In the second case, you build a custom bit of code to import the data as entities (ex: nodes, comments, users) which gives you the use of the Entity and Field APIs but you're now disconnected from the data source. You need to maintain a data sync or run batch updates on data in Drupal and/or in the original data set. This also brings up the issue of "big data" in Drupal. The default table structure in Drupal normalizes the data. Which means running updates may be very expensive.

Not to mention, in the second case, most of this code is single purpose and not necessarily reusable.

Goal

Based on the problems above with the two current implementations we set out to make a solution that both allows the use of the Entity and Field APIs in Drupal and avoided the issue of syncing data and performing batch updates.

We also wanted to ensure that the solution would be compatible with existing contrib modules in Drupal. Meaning you could treat data from web services as you would data from Drupal's own tables.

Lastly, we wanted to ensure that the solution was reusable. Meaning it could be repurposed to work with nearly any web service with nearly any kind of data being returned.

Initial Concept Implementation

We came up with three components to generically describe each portion required for interacting with web service data.

  • Connector: A tool or library which handled the request medium (ex: HTTP)
  • Processor: An object which would convert the data from the web service into a standard format which could be interpreted by Drupal
  • Configuration Type: An entity which told Drupal which connector to use with which web service, which processor to use to parse the data and what data we wanted to extract from that service

For the connector, we had an existing module we used to make REST based queries called RESTClient which we extended to support the "WsConnector" class. We created a hook called hook_wsconfig_connector_info which allowed modules to tell wsdata that they implement WsConnector.

Next, the configuration object. We created an entity type called "wsconfig" and a bundle entity type "wsconfig_type". This allowed us create a one-to-one relationship between connector types and configuration types. For example, you would create a wsconfig type called "My REST Services", set the root URL for the services and define the connector to use as "RESTClient". You could then create a second wsconfig type called "My SOAP Services" which pointed to the SOAP web service root URL and used a SOAP compatible connector.

Finally, we needed a way to map a local data container (ex: field instance) to a remote data point (ex: value from remote XML element). To accomplish this we created "wsfields". The goal being to map an individual field value to a value from a web service.

Using hook_field_storage_pre_load we told Drupal to ignore loading a value for the given field instance as we would load and format the data from the web service instead. This is where the processors come in. As an example, say you have a field on your user entities called "First Name". You would go to that field's settings form and set it to use a wsconfig instance to connect and load data. Next you set any query parameters or replacement patterns for the connector call (ex: /service/user/%uid would need %uid replace with the user's uid value). Then set which 'remote key' to use from the returned data as the value for the field itself.

Similarly, using hook_field_storage_pre_insert the same general process applies to writing data. The only difference being we send data to the service using the wsconfig information.

Best of all, you could have a mixed environment of field instances. Meaning an instance of the "body" field on a node article could use data from the database whereas the "body" on another node type could use wsdata instead.

Issues with the Concept

For very basic reads and writes the service code worked very well. It was configurable from the UI and was specific to Field Instances, rather than the field definition itself. However, problems quickly arose from using hook_field_storage_pre_load/insert.

The most glaring issue was dealing with EntityFieldQueries. In short, they could never work. Which meant modules such as efq_views and other complex modules such as Panels would not properly read and/or write data to said fields.

Search API also failed to index the data and actually caused exceptions to be thrown as it became confused by the data handling. The i18n module had similar issues dealing with the fields in their current implementation.

We had achieved two of the three goals we had original sought out, but missing the last part, the compatibility with contrib modules, was a deal breaker.

Second Attempt

After reviewing the issues with the first implementation, we came to the conclusion that most (if not all) of the issues revolved around EntityFieldQueries failing on wsdata fields. Meaning we needed to implement a proper Field Storage Controller with support for EntityFieldQueries (i.e implement hook_field_storage_query).

All the same principles applied. We used connectors, processors and configurations to interact with web service data. The specific field settings were moved into the "field settings" instead of "field instance settings". Using the "storage" array in the field settings, you define the storage settings, remote key and other information previously only found in the configuration entity. This allowed the configuration entities to act more generically. They could be mapped one-to-one per web service instead of per field.

Here's a snippet from a field definition using the Web Service Fields Storage controller:


'storage' => array(
  'module' => 'wsfields_storage',
  'settings' => array(
    'processor' => 'myprocessor',
    'propertymap' => array(
      'read' => array(
        '%uid' => 'uid',
      ),
    ),
    'remotekey' => 'description',
    'translation' => FALSE,
    'wsconfig_name' => 'my_wsconfig',
  ),
  'type' => 'wsfields_storage',

Issues with the Second Attempt

Our second implementation met all our primary goals. However we did lose some features we had from the initial implementation.

No longer were the settings defined on field instances. Instead they were defined in the "storage" sub array in the field settings. This meant two drawbacks:

  • No longer configurable through the UI: Since Drupal cannot change a field's storage controller once it is defined, changes to a field defined by the UI are impossible
  • All instances of a given field must use the storage controller. This more than likely means less sharing of fields between entities and entity types.

Future

The same concepts could be applied to entities themselves. Build a generic entity controller which uses web services to load all of it's data. This is more complex to accomplish than using fields. With fields, the entity to which they're attached can store information about how to load the appropriate data. If the entity itself is entirely remote, knowing how or where to load the data gets harder. Even knowing if the given entity exists at all is more difficult.

However we do have a basic implementation almost working. It can read from a service which supplies all the entity data already configured (using Services on another Drupal site).

wsdata's People

Contributors

classiccut avatar minoroffense avatar ptsimard avatar sjaffery avatar spotzero avatar

Stargazers

 avatar

Watchers

 avatar  avatar  avatar

wsdata's Issues

Just an Error (wsfield)

Error: Call to a member function call() on null in Drupal\wsdata\WSDataService->call() (line 29 of /var/www/my_project/web/modules/contrib/wsdata/src/WSDataService.php) #0 /var/www/my_project/web/modules/contrib/wsdata/modules/wsdata_field/wsdata_field.module(71): Drupal\wsdata\WSDataService->call(NULL, NULL, Array, '', Array, 'videos:0:video_...', Array) #1 /var/www/my_project/web/core/lib/Drupal/Core/Entity/EntityStorageBase.php(301): wsdata_field_entity_load(Array, 'node') #2 /var/www/my_project/web/core/lib/Drupal/Core/Entity/EntityStorageBase.php(249): Drupal\Core\Entity\EntityStorageBase->postLoad(Array) #3 /var/www/my_project/web/core/modules/views/src/Plugin/views/query/Sql.php(1563): Drupal\Core\Entity\EntityStorageBase->loadMultiple(Array) #4 /var/www/my_project/web/core/modules/views/src/Plugin/views/query/Sql.php(1488): Drupal\views\Plugin\views\query\Sql->loadEntities(Array) #5 /var/www/my_project/web/core/modules/views/src/ViewExecutable.php(1423): Drupal\views\Plugin\views\query\Sql->execute(Object(Drupal\views\ViewExecutable)) #6 /var/www/my_project/web/core/modules/views/src/ViewExecutable.php(1451): Drupal\views\ViewExecutable->execute(NULL) #7 /var/www/my_project/web/core/modules/views/src/Plugin/views/display/Page.php(171): Drupal\views\ViewExecutable->render() #8 /var/www/my_project/web/core/modules/views/src/ViewExecutable.php(1627): Drupal\views\Plugin\views\display\Page->execute() #9 /var/www/my_project/web/core/modules/views/src/Element/View.php(77): Drupal\views\ViewExecutable->executeDisplay('page_1', Array) #10 [internal function]: Drupal\views\Element\View::preRenderViewElement(Array) #11 /var/www/my_project/web/core/lib/Drupal/Core/Render/Renderer.php(378): call_user_func(Array, Array) #12 /var/www/my_project/web/core/lib/Drupal/Core/Render/Renderer.php(195): Drupal\Core\Render\Renderer->doRender(Array, false) #13 /var/www/my_project/web/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php(226): Drupal\Core\Render\Renderer->render(Array, false) #14 /var/www/my_project/web/core/lib/Drupal/Core/Render/Renderer.php(576): Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent{closure}() #15 /var/www/my_project/web/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php(227): Drupal\Core\Render\Renderer->executeInRenderContext(Object(Drupal\Core\Render\RenderContext), Object(Closure)) #16 /var/www/my_project/web/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php(117): Drupal\Core\Render\MainContent\HtmlRenderer->prepare(Array, Object(Symfony\Component\HttpFoundation\Request), Object(Drupal\Core\Routing\CurrentRouteMatch)) #17 /var/www/my_project/web/core/lib/Drupal/Core/EventSubscriber/MainContentViewSubscriber.php(90): Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse(Array, Object(Symfony\Component\HttpFoundation\Request), Object(Drupal\Core\Routing\CurrentRouteMatch)) #18 /var/www/my_project/web/core/lib/Drupal/Component/EventDispatcher/ContainerAwareEventDispatcher.php(108): Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray(Object(Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent), 'kernel.view', Object(Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher)) #19 /var/www/my_project/vendor/symfony/http-kernel/HttpKernel.php(158): Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch('kernel.view', Object(Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent)) #20 /var/www/my_project/vendor/symfony/http-kernel/HttpKernel.php(68): Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request), 1) #21 /var/www/my_project/web/core/lib/Drupal/Core/StackMiddleware/Session.php(57): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #22 /var/www/my_project/web/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(47): Drupal\Core\StackMiddleware\Session->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #23 /var/www/my_project/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(99): Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #24 /var/www/my_project/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(78): Drupal\page_cache\StackMiddleware\PageCache->pass(Object(Symfony\Component\HttpFoundation\Request), 1, true) #25 /var/www/my_project/web/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(47): Drupal\page_cache\StackMiddleware\PageCache->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #26 /var/www/my_project/web/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(50): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #27 /var/www/my_project/vendor/stack/builder/src/Stack/StackedHttpKernel.php(23): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #28 /var/www/my_project/web/core/lib/Drupal/Core/DrupalKernel.php(657): Stack\StackedHttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #29 /var/www/my_project/web/index.php(19): Drupal\Core\DrupalKernel->handle(Object(Symfony\Component\HttpFoundation\Request)) #30 {main}.

8.x: Formatting options not available in Views

Hi,

When showing WS Data fields in Views I cannot select any formatting options.
For example, I load a float via the web service, and I want to show it as a price in the view (prepended with currency symbol, rounded to 2 digits).

Within Views it is not possible to set these formatting options for any type of WS Field.

Reproducable by adding any type of field that has formatting options to a view

Notice: Undefined index: headers in Drupal\wsdata\Plugin\WSConnectorBase->saveOptions()

Possibly related to #17

Notice: Undefined index: headers in Drupal\wsdata\Plugin\WSConnectorBase->saveOptions() (line 166 of modules/custom/wsdata/src/Plugin/WSConnectorBase.php).
Drupal\wsdata\Plugin\WSConnectorBase->saveOptions(Array) (Line: 84)
Drupal\wsdata\Plugin\WSConnector\WSConnectorSimpleHTTP->saveOptions(Array) (Line: 169)
Drupal\wsdata\Entity\WSCall->setOptions(Array) (Line: 190)
Drupal\wsdata\Form\WSCallForm->save(Array, Object)
call_user_func_array(Array, Array) (Line: 111)
Drupal\Core\Form\FormSubmitter->executeSubmitHandlers(Array, Object) (Line: 51)
Drupal\Core\Form\FormSubmitter->doSubmitForm(Array, Object) (Line: 585)
Drupal\Core\Form\FormBuilder->processForm('wscall_edit_form', Array, Object) (Line: 314)
Drupal\Core\Form\FormBuilder->buildForm('wscall_edit_form', Object) (Line: 74)
Drupal\Core\Controller\FormController->getContentResult(Object, Object)
call_user_func_array(Array, Array) (Line: 123)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber{closure}() (Line: 576)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 124)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) (Line: 97)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber{closure}()
call_user_func_array(Object, Array) (Line: 153)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 68)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 57)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 99)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 78)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 50)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 657)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)

Notice: Undefined variable: existing_field_storage_options in Drupal\wsdata_field\Form\WSFieldAddFieldForm->buildForm()

Notice: Undefined variable: existing_field_storage_options in Drupal\wsdata_field\Form\WSFieldAddFieldForm->buildForm() (line 123 of modules/custom/wsdata/modules/wsdata_field/src/Form/WSFieldAddFieldForm.php).
Drupal\wsdata_field\Form\WSFieldAddFieldForm->buildForm(Array, Object, 'node', 'pornstar')
call_user_func_array(Array, Array) (Line: 514)
Drupal\Core\Form\FormBuilder->retrieveForm('wsfield_field_add_form', Object) (Line: 271)
Drupal\Core\Form\FormBuilder->buildForm('wsfield_field_add_form', Object) (Line: 74)
Drupal\Core\Controller\FormController->getContentResult(Object, Object)
call_user_func_array(Array, Array) (Line: 123)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber{closure}() (Line: 576)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 124)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) (Line: 97)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber{closure}()
call_user_func_array(Object, Array) (Line: 153)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 68)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 57)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 99)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 78)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 50)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 657)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)

The website encountered an unexpected error.

The website encountered an unexpected error. Please try again later.

Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException: You have requested a non-existent service "plugin.manager.wsfieldconfig". Did you mean one of these: "plugin.manager.field.widget", "plugin.manager.wsencoder", "plugin.manager.wsdecoder"? in Drupal\Component\DependencyInjection\Container->get() (line 151 of core/lib/Drupal/Component/DependencyInjection/Container.php).

Drupal\wsdata_field\Form\WSFieldConfigForm::create(Object) (Line: 28)
Drupal\Core\DependencyInjection\ClassResolver->getInstanceFromDefinition('Drupal\wsdata_field\Form\WSFieldConfigForm') (Line: 187)
Drupal\Core\Entity\EntityTypeManager->getFormObject('wsfield_config', 'edit') (Line: 105)
Drupal\Core\Entity\EntityManager->getFormObject('wsfield_config', 'edit') (Line: 69)
Drupal\Core\Entity\HtmlEntityFormController->getFormObject(Object, 'wsfield_config.edit.default') (Line: 59)
Drupal\Core\Controller\FormController->getContentResult(Object, Object)
call_user_func_array(Array, Array) (Line: 123)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber{closure}() (Line: 576)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 124)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) (Line: 97)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber{closure}()
call_user_func_array(Object, Array) (Line: 153)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 68)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 57)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 99)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 78)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 50)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 657)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)

Notice: Undefined index: headers_count in

Notice: Undefined index: headers_count in Drupal\wsdata\Plugin\WSConnector\WSConnectorSimpleHTTP->getOptionsForm() (line 122 of modules/custom/wsdata/src/Plugin/WSConnector/WSConnectorSimpleHTTP.php).
Drupal\wsdata\Plugin\WSConnector\WSConnectorSimpleHTTP->getOptionsForm(Array) (Line: 191)
Drupal\wsdata\Entity\WSCall->getOptionsForm(NULL, Array) (Line: 119)
Drupal\wsdata\Form\WSCallForm->form(Array, Object) (Line: 117)
Drupal\Core\Entity\EntityForm->buildForm(Array, Object)
call_user_func_array(Array, Array) (Line: 514)
Drupal\Core\Form\FormBuilder->retrieveForm('wscall_edit_form', Object) (Line: 271)
Drupal\Core\Form\FormBuilder->buildForm('wscall_edit_form', Object) (Line: 74)
Drupal\Core\Controller\FormController->getContentResult(Object, Object)
call_user_func_array(Array, Array) (Line: 123)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber{closure}() (Line: 576)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 124)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) (Line: 97)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber{closure}()
call_user_func_array(Object, Array) (Line: 153)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 68)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 57)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 99)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 78)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 50)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 657)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)

WSFields not showing up in Search Index

When I attempt to create a search index for my content type none of the WSFields in that content type appear in the list of fields available for that index.

Token Replacement Doesn't Seem To Work

I had a replacement string in my path...

"search?id=44bc40f3bc04f65b7a35&thumbsize=medium&stars=[person]"

I wanted to replace it with the node title or any other field for that matter and the debug shows this.

'replacements' => array(1)
'person' => string(12) "[node:title]"

I suspect that this is not working right. It looks like to me it literally used [node:title] as the value of the string.

I have no idea why. When I try creating a field, I get this.

TypeError: Argument 1 passed to Drupal\wsdata\WSDataService::__construct() must be an instance of Drupal\Core\Entity\EntityTypeManager, instance of Drupal\webprofiler\Entity\EntityManagerWrapper given, called in /var/www/my_project/web/core/lib/Drupal/Component/DependencyInjection/Container.php on line 262 in Drupal\wsdata\WSDataService->__construct() (line 17 of /var/www/my_project/web/modules/contrib/wsdata/src/WSDataService.php) #0 /var/www/my_project/web/core/lib/Drupal/Component/DependencyInjection/Container.php(262): Drupal\wsdata\WSDataService->construct(Object(Drupal\webprofiler\Entity\EntityManagerWrapper)) #1 /var/www/my_project/web/core/lib/Drupal/Component/DependencyInjection/Container.php(171): Drupal\Component\DependencyInjection\Container->createService(Array, 'wsdata') #2 /var/www/my_project/web/core/lib/Drupal.php(158): Drupal\Component\DependencyInjection\Container->get('wsdata') #3 /var/www/my_project/web/modules/contrib/wsdata/modules/wsdata_field/src/Form/WSFieldConfigForm.php(92): Drupal::service('wsdata') #4 /var/www/my_project/web/core/lib/Drupal/Core/Entity/EntityForm.php(117): Drupal\wsdata_field\Form\WSFieldConfigForm->form(Array, Object(Drupal\Core\Form\FormState)) #5 /var/www/my_project/web/modules/contrib/wsdata/modules/wsdata_field/src/Form/WSFieldConfigForm.php(51): Drupal\Core\Entity\EntityForm->buildForm(Array, Object(Drupal\Core\Form\FormState)) #6 [internal function]: Drupal\wsdata_field\Form\WSFieldConfigForm->buildForm(Array, Object(Drupal\Core\Form\FormState), 'node.article.fi...') #7 /var/www/my_project/web/core/lib/Drupal/Core/Form/FormBuilder.php(514): call_user_func_array(Array, Array) #8 /var/www/my_project/web/core/lib/Drupal/Core/Form/FormBuilder.php(271): Drupal\Core\Form\FormBuilder->retrieveForm('wsfield_config...', Object(Drupal\Core\Form\FormState)) #9 /var/www/my_project/web/core/lib/Drupal/Core/Controller/FormController.php(74): Drupal\Core\Form\FormBuilder->buildForm('wsfield_config...', Object(Drupal\Core\Form\FormState)) #10 [internal function]: Drupal\Core\Controller\FormController->getContentResult(Object(Symfony\Component\HttpFoundation\Request), Object(Drupal\Core\Routing\RouteMatch)) #11 /var/www/my_project/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(123): call_user_func_array(Array, Array) #12 /var/www/my_project/web/core/lib/Drupal/Core/Render/Renderer.php(576): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber{closure}() #13 /var/www/my_project/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(124): Drupal\Core\Render\Renderer->executeInRenderContext(Object(Drupal\Core\Render\RenderContext), Object(Closure)) #14 /var/www/my_project/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(97): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) #15 [internal function]: Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber{closure}() #16 /var/www/my_project/vendor/symfony/http-kernel/HttpKernel.php(153): call_user_func_array(Object(Closure), Array) #17 /var/www/my_project/vendor/symfony/http-kernel/HttpKernel.php(68): Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request), 1) #18 /var/www/my_project/web/core/lib/Drupal/Core/StackMiddleware/Session.php(57): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #19 /var/www/my_project/web/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(47): Drupal\Core\StackMiddleware\Session->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #20 /var/www/my_project/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(99): Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #21 /var/www/my_project/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(78): Drupal\page_cache\StackMiddleware\PageCache->pass(Object(Symfony\Component\HttpFoundation\Request), 1, true) #22 /var/www/my_project/web/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(47): Drupal\page_cache\StackMiddleware\PageCache->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #23 /var/www/my_project/web/modules/contrib/devel/webprofiler/src/StackMiddleware/WebprofilerMiddleware.php(38): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #24 /var/www/my_project/web/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(50): Drupal\webprofiler\StackMiddleware\WebprofilerMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #25 /var/www/my_project/vendor/stack/builder/src/Stack/StackedHttpKernel.php(23): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #26 /var/www/my_project/web/core/lib/Drupal/Core/DrupalKernel.php(657): Stack\StackedHttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #27 /var/www/my_project/web/index.php(19): Drupal\Core\DrupalKernel->handle(Object(Symfony\Component\HttpFoundation\Request)) #28 {main}.

demo wikipedia does not work

Hello,

I am trying to test the use of the wsdata module, but I encounter some problems, certainly configuration problems.

All modules required for wsdata are enabled and up-to-date.

Before performing a test on our rest services, I wanted to test at first the wikipedia demo. But it turns out that this demo does not work (it does not show anything at all in the Remote text).
A test on our service produces the same result

The drupal version used is 7.54.

Do you have any ideas ?

Thank you in advance.

Help and Tooltips

I thought maybe it might be beneficial to start with a benign and easy API endpoint for GET requests just to illustrate a basic configuration. This would allow us to maybe assist the end user when they are setting up configuration. I also don't mind writing some overall documentation that's more advanced for the actual Help section. Let's start with the Star Wars API

Endpoints

https://swapi.co/api

HTTP 200 OK
Content-Type: application/json
Allow: GET, HEAD, OPTIONS
Vary: Accept

{
    "people": "https://swapi.co/api/people/", 
    "planets": "https://swapi.co/api/planets/", 
    "films": "https://swapi.co/api/films/", 
    "species": "https://swapi.co/api/species/", 
    "vehicles": "https://swapi.co/api/vehicles/", 
    "starships": "https://swapi.co/api/starships/"
}

If I use https://swapi.co/api/people I see several results of which I can append a number to the URL and get a result or I can simply see all the results. https://swapi.co/api/people/1

HTTP 200 OK
Content-Type: application/json
Allow: GET, HEAD, OPTIONS
Vary: Accept

{
    "count": 87, 
    "next": "https://swapi.co/api/people/?page=2", 
    "previous": null, 
    "results": [
        {
            "name": "Luke Skywalker", 
            "height": "172", 
            "mass": "77", 
            "hair_color": "blond", 
            "skin_color": "fair", 
            "eye_color": "blue", 
            "birth_year": "19BBY", 
            "gender": "male", 
            "homeworld": "https://swapi.co/api/planets/1/", 
            "films": [
                "https://swapi.co/api/films/2/", 
                "https://swapi.co/api/films/6/", 
                "https://swapi.co/api/films/3/", 
                "https://swapi.co/api/films/1/", 
                "https://swapi.co/api/films/7/"
            ], 
            "species": [
                "https://swapi.co/api/species/1/"
            ], 
            "vehicles": [
                "https://swapi.co/api/vehicles/14/", 
                "https://swapi.co/api/vehicles/30/"
            ], 
            "starships": [
                "https://swapi.co/api/starships/12/", 
                "https://swapi.co/api/starships/22/"
            ], 
            "created": "2014-12-09T13:50:51.644000Z", 
            "edited": "2014-12-20T21:17:56.891000Z", 
            "url": "https://swapi.co/api/people/1/"
        }, 
        {
            "name": "C-3PO", 
            "height": "167", 
            "mass": "75", 
            "hair_color": "n/a", 
            "skin_color": "gold", 
            "eye_color": "yellow", 
            "birth_year": "112BBY", 
            "gender": "n/a", 
            "homeworld": "https://swapi.co/api/planets/1/", 
            "films": [
                "https://swapi.co/api/films/2/", 
                "https://swapi.co/api/films/5/", 
                "https://swapi.co/api/films/4/", 
                "https://swapi.co/api/films/6/", 
                "https://swapi.co/api/films/3/", 
                "https://swapi.co/api/films/1/"
            ], 
            "species": [
                "https://swapi.co/api/species/2/"
            ], 
            "vehicles": [], 
            "starships": [], 
            "created": "2014-12-10T15:10:51.357000Z", 
            "edited": "2014-12-20T21:17:50.309000Z", 
            "url": "https://swapi.co/api/people/2/"
        }, 
        {
            "name": "R2-D2", 
            "height": "96", 
            "mass": "32", 
            "hair_color": "n/a", 
            "skin_color": "white, blue", 
            "eye_color": "red", 
            "birth_year": "33BBY", 
            "gender": "n/a", 
            "homeworld": "https://swapi.co/api/planets/8/", 
            "films": [
                "https://swapi.co/api/films/2/", 
                "https://swapi.co/api/films/5/", 
                "https://swapi.co/api/films/4/", 
                "https://swapi.co/api/films/6/", 
                "https://swapi.co/api/films/3/", 
                "https://swapi.co/api/films/1/", 
                "https://swapi.co/api/films/7/"
            ], 
            "species": [
                "https://swapi.co/api/species/2/"
            ], 
            "vehicles": [], 
            "starships": [], 
            "created": "2014-12-10T15:11:50.376000Z", 
            "edited": "2014-12-20T21:17:50.311000Z", 
            "url": "https://swapi.co/api/people/3/"
        }, 
        {
            "name": "Darth Vader", 
            "height": "202", 
            "mass": "136", 
            "hair_color": "none", 
            "skin_color": "white", 
            "eye_color": "yellow", 
            "birth_year": "41.9BBY", 
            "gender": "male", 
            "homeworld": "https://swapi.co/api/planets/1/", 
            "films": [
                "https://swapi.co/api/films/2/", 
                "https://swapi.co/api/films/6/", 
                "https://swapi.co/api/films/3/", 
                "https://swapi.co/api/films/1/"
            ], 
            "species": [
                "https://swapi.co/api/species/1/"
            ], 
            "vehicles": [], 
            "starships": [
                "https://swapi.co/api/starships/13/"
            ], 
            "created": "2014-12-10T15:18:20.704000Z", 
            "edited": "2014-12-20T21:17:50.313000Z", 
            "url": "https://swapi.co/api/people/4/"
        }, 
        {
            "name": "Leia Organa", 
            "height": "150", 
            "mass": "49", 
            "hair_color": "brown", 
            "skin_color": "light", 
            "eye_color": "brown", 
            "birth_year": "19BBY", 
            "gender": "female", 
            "homeworld": "https://swapi.co/api/planets/2/", 
            "films": [
                "https://swapi.co/api/films/2/", 
                "https://swapi.co/api/films/6/", 
                "https://swapi.co/api/films/3/", 
                "https://swapi.co/api/films/1/", 
                "https://swapi.co/api/films/7/"
            ], 
            "species": [
                "https://swapi.co/api/species/1/"
            ], 
            "vehicles": [
                "https://swapi.co/api/vehicles/30/"
            ], 
            "starships": [], 
            "created": "2014-12-10T15:20:09.791000Z", 
            "edited": "2014-12-20T21:17:50.315000Z", 
            "url": "https://swapi.co/api/people/5/"
        }, 
        {
            "name": "Owen Lars", 
            "height": "178", 
            "mass": "120", 
            "hair_color": "brown, grey", 
            "skin_color": "light", 
            "eye_color": "blue", 
            "birth_year": "52BBY", 
            "gender": "male", 
            "homeworld": "https://swapi.co/api/planets/1/", 
            "films": [
                "https://swapi.co/api/films/5/", 
                "https://swapi.co/api/films/6/", 
                "https://swapi.co/api/films/1/"
            ], 
            "species": [
                "https://swapi.co/api/species/1/"
            ], 
            "vehicles": [], 
            "starships": [], 
            "created": "2014-12-10T15:52:14.024000Z", 
            "edited": "2014-12-20T21:17:50.317000Z", 
            "url": "https://swapi.co/api/people/6/"
        }, 
        {
            "name": "Beru Whitesun lars", 
            "height": "165", 
            "mass": "75", 
            "hair_color": "brown", 
            "skin_color": "light", 
            "eye_color": "blue", 
            "birth_year": "47BBY", 
            "gender": "female", 
            "homeworld": "https://swapi.co/api/planets/1/", 
            "films": [
                "https://swapi.co/api/films/5/", 
                "https://swapi.co/api/films/6/", 
                "https://swapi.co/api/films/1/"
            ], 
            "species": [
                "https://swapi.co/api/species/1/"
            ], 
            "vehicles": [], 
            "starships": [], 
            "created": "2014-12-10T15:53:41.121000Z", 
            "edited": "2014-12-20T21:17:50.319000Z", 
            "url": "https://swapi.co/api/people/7/"
        }, 
        {
            "name": "R5-D4", 
            "height": "97", 
            "mass": "32", 
            "hair_color": "n/a", 
            "skin_color": "white, red", 
            "eye_color": "red", 
            "birth_year": "unknown", 
            "gender": "n/a", 
            "homeworld": "https://swapi.co/api/planets/1/", 
            "films": [
                "https://swapi.co/api/films/1/"
            ], 
            "species": [
                "https://swapi.co/api/species/2/"
            ], 
            "vehicles": [], 
            "starships": [], 
            "created": "2014-12-10T15:57:50.959000Z", 
            "edited": "2014-12-20T21:17:50.321000Z", 
            "url": "https://swapi.co/api/people/8/"
        }, 
        {
            "name": "Biggs Darklighter", 
            "height": "183", 
            "mass": "84", 
            "hair_color": "black", 
            "skin_color": "light", 
            "eye_color": "brown", 
            "birth_year": "24BBY", 
            "gender": "male", 
            "homeworld": "https://swapi.co/api/planets/1/", 
            "films": [
                "https://swapi.co/api/films/1/"
            ], 
            "species": [
                "https://swapi.co/api/species/1/"
            ], 
            "vehicles": [], 
            "starships": [
                "https://swapi.co/api/starships/12/"
            ], 
            "created": "2014-12-10T15:59:50.509000Z", 
            "edited": "2014-12-20T21:17:50.323000Z", 
            "url": "https://swapi.co/api/people/9/"
        }, 
        {
            "name": "Obi-Wan Kenobi", 
            "height": "182", 
            "mass": "77", 
            "hair_color": "auburn, white", 
            "skin_color": "fair", 
            "eye_color": "blue-gray", 
            "birth_year": "57BBY", 
            "gender": "male", 
            "homeworld": "https://swapi.co/api/planets/20/", 
            "films": [
                "https://swapi.co/api/films/2/", 
                "https://swapi.co/api/films/5/", 
                "https://swapi.co/api/films/4/", 
                "https://swapi.co/api/films/6/", 
                "https://swapi.co/api/films/3/", 
                "https://swapi.co/api/films/1/"
            ], 
            "species": [
                "https://swapi.co/api/species/1/"
            ], 
            "vehicles": [
                "https://swapi.co/api/vehicles/38/"
            ], 
            "starships": [
                "https://swapi.co/api/starships/48/", 
                "https://swapi.co/api/starships/59/", 
                "https://swapi.co/api/starships/64/", 
                "https://swapi.co/api/starships/65/", 
                "https://swapi.co/api/starships/74/"
            ], 
            "created": "2014-12-10T16:16:29.192000Z", 
            "edited": "2014-12-20T21:17:50.325000Z", 
            "url": "https://swapi.co/api/people/10/"
        }
    ]
}

Walkthrough

Walk me through the process of setting the people endpoint up with WSDATA to store the "species" field in a WSFIELD for a content type.

bug - plugin.manager.wsfieldconfig

The following error occurs when adding a new wsdata field. This occurs on version 8.x-1.0-alpha3; note that updating to the latest dev version did solve the error for me.

[php7:notice] [pid 23094] [client xx.xx.xx.xx:45714] Uncaught PHP Exception Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException: "You have requested a non-existent service "plugin.manager.wsfieldconfig". Did you mean one of these: "plugin.manager.field.widget", "plugin.manager.wsencoder", "plugin.manager.wsdecoder"?" at /var/www/html/dev/dev-configuration-wsdata/web/core/lib/Drupal/Component/DependencyInjection/Container.php line 151, referer: https://dev-configuration-wsdata.xxxx.xxxx.ca/admin/structure/types/manage/street_addresses/fields/add-wsfield

wsdata blocks can't be placed

I love the idea of what this is intended to do but I can't seem to place it in the blocks layout. It just spins the loading icon and does nothing at the moment.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.