Problem/Motivation

The TypedData Any defines this type as:

The "any" data type does not implement a list or complex data interface, nor is it mappable to any primitive type. Thus, it may contain any PHP data for which no further metadata is available.

It explicitly forbids the value it stores "implement a list or complex data interface, nor is it mappable to any primitive type". However, its code implementation does not check those conditions above.

Proposed resolution

In the implementation, override the setValue(), then check the conditions, and throw exceptions when the conditions are not met.

Update the docs to make it clear

Remaining tasks

1. Write the patch above, and see how much impact this change will have in Core
2. Decide if we can make the change for D8, if not, maybe deprecate Any, and create "AnyBut" type?

Test documentation with a few people, and if possible, provide an example

User interface changes

None.

API changes

None.

Data model changes

None.

Comments

skyredwang created an issue. See original summary.

lawxen’s picture

Assigned: Unassigned » lawxen
lawxen’s picture

@skyredwang

Data model changes

This type no longer can store array, primitive or known object implementing complex data interface.

The goal may be not ideal:

Reason:

  1. All datas that is an object should use 'any' type data no matter whether it implementing complex data interface.
    Because no other type data can be or should be used to store object.
  2. 'any' type data should have the ability to store any primitive data, Just like plugin system, we may pass different primite type of data to it on different plugin instance

Conclusion

  1. The 'any' type data should be the last choice when module don't have any other suitable choice, It should have the ability to store any data, So we shouldn't add any condition to it on setValue()
  2. What we should do is: When module come to the situation(.....) to use 'any', we should make these situation can be serialized

      possible situation:

    1. Object:when pass an object to any, don't just return the object, return the result of normalize(object)
lawxen’s picture

StatusFileSize
new1.31 KB

Make class Any overwrite setValue to add conditions

  1. don't allow array data
  2. don't allow data that implements ComplexDataInterface
  3. don't allow data that implements PrimitiveInterface
lawxen’s picture

StatusFileSize
new911 bytes
new1.44 KB

List:

core/core.api.php#n994

List data types, with interface \Drupal\Core\TypedData\ListInterface,
represent data that is an ordered list of typed data, all of the same type.

core/lib/Drupal/Core/TypedData/Annotation/DataType.php#n21

Furthermore, lists of data items are represented by objects implementing the
\Drupal\Core\TypedData\ListInterface. A list contains items of the same data
type,the plugins in the list must have the same base plugin ID;

Map:

core/core.api.php#n984

The base type for most complex data is the
\Drupal\Core\TypedData\Plugin\DataType\Map class, which represents an associative array

We can see that both *map* and *list* represents a diferent subset of Array

So all map and list's setValue() check whether the value is an array is correct(the father of data that map and list should reprents)

core/lib/Drupal/Core/TypedData/Plugin/DataType/ItemList.php#n58

      if (!is_array($values)) {
        throw new \InvalidArgumentException('Cannot set a list with a non-array value.');
      }

core/lib/Drupal/Core/TypedData/Plugin/DataType/Map.php#n75

     if (isset($values) && !is_array($values)) {
      throw new \InvalidArgumentException("Invalid values given. Values must be represented as an associative array.");
    }

Come to Any

Any:

core/lib/Drupal/Core/TypedData/Plugin/DataType/Any.php#n10

The "any" data type does not implement a list or complex data interface, nor
 is it mappable to any primitive type. Thus, it may contain any PHP data for
 which no further metadata is available.  

Let's fouced on: any PHP data for "which no further metadata is available"

The core/core.api.php#n941 describe the metadata here:

The metadata of a data object is defined by an object based on a class called the definition class

Conclusion

The list or complex data interface corresponding to the typed data, not the value stored by typed data
So we shouldn't forbid any typed data store data which implement ComplexDataInterface,ListInterface or PrimiteInterface

So If we add condition on any.php's setValue() according to doc(Not sure whether we should add condition)
we should forbid the data which implements DataDefinitionInterface

  class Any extends TypedData {

  protected $value;

  public function setValue($value, $notify = TRUE) {
    if (is_array($value) && $value instanceof DataDefinitionInterface) {
      throw new \InvalidArgumentException("Invalid value given, Value must not be implement DataDefinitionInterface.");
    }
    parent::setValue($value, $notify);
  }
}

If the 'any' doc is the formal specification,The above is the right formal implementation

Above formal implementation make a restrictions on 'any'
we can't store a typed data to a typed data of 'any'

dawehner’s picture

So If we add condition on any.php's setValue() according to doc(Not sure whether we should add condition)
we should forbid the data which implements DataDefinitionInterface

Isn't the usecase of any when you simply don't know upfront? Just imagine storing arbitrary JSON, which could be all of the different variants you listed above ...

tedbow’s picture

I think agree with @dawehner here

The doc in Any

* The "any" data type does not implement a list or complex data interface, nor
 * is it mappable to any primitive type. Thus, it may contain any PHP data for
 * which no further metadata is available.

might not be very clear.

I wonder the intention of the last sentence is actually

Thus, it may contain any PHP data for which no further metadata is available beforehand.

Meaning you can store values have metaData but you if you have metadata beforehand about what type of data you will be storing you should not use Any.

lawxen’s picture

@tedbow
I agree with you and @dawehner
I add the word 'beforehand' @tedbow write to the doc on 2915052-8.patch, Please forgive my directing use of what you write, I want to accelerate the fixing of the issue, then hope @fago can review the patch, he wrote the origin comment on https://www.drupal.org/node/1913328

lawxen’s picture

StatusFileSize
new600 bytes
new1.11 KB
skyredwang’s picture

Why don't we get rid off the first sentence, and change the documentation to:

It may contain any PHP data for which no further metadata is available beforehand.

Any really means any.

wim leers’s picture

Title: TypedData Any isn't consistent with its documentation » TypedData's "Any" @DataType plugin has unclear documentation
Status: Active » Needs review
Issue tags: +API-First Initiative
StatusFileSize
new878 bytes

API-First issue #2915705: TypedData 'Any' can't be normalized to array if it stores an object triggered this.

I agree with #10. But I think we can still include the relevant bit of the first sentence, in a much clearer way (thanks to #10). Since I didn't do literally what #10 suggested, I can't RTBC this.

wim leers’s picture

borisson_’s picture

Status: Needs review » Reviewed & tested by the community

This makes it a lot cleaner, thanks Wim!

xjm’s picture

Status: Reviewed & tested by the community » Needs review

Hm, so I'm not sure just swapping the order of the sentences makes it any clearer...

How about adding an example?

xjm’s picture

Also the summary claims this is a data model change but the issue title says it's a docs fix?

Thanks!

skyredwang’s picture

Issue summary: View changes

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

smustgrave’s picture

Status: Needs review » Needs work
Issue tags: +Needs issue summary update, +Needs Review Queue Initiative

This issue is being reviewed by the kind folks in Slack, #needs-review-queue-initiative. We are working to keep the size of Needs Review queue [2700+ issues] to around 400 (1 month or less), following Review a patch or merge request as a guide.

Tagging for IS per #14 asking for an example.

lawxen’s picture

Assigned: lawxen » Unassigned

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.