Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[LDAP] Add "applyOperations" method to EntryManager #27069

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 18, 2018

Conversation

mablae
Copy link
Contributor

@mablae mablae commented Apr 26, 2018

Q A
Branch? master
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets #27039
License MIT
Doc PR symfony/symfony-docs#9715

This PR adds a new method called applyOperations to the LDAP EntryManager class.
Internally it is mapping the new UpdateOperation object to the ldap_modify_batch method.

Tests green against openldap.

Thanks for any feedback.

Todo:

  • Add Docs PR

@mablae mablae changed the title Add modifyBatch method to LDAP EntryManager [LDAP] Add modifyBatch method to EntryManager Apr 26, 2018
@mablae mablae force-pushed the feature-ldap-batch branch from fc42f19 to 7395dfd Compare April 26, 2018 22:04

/**
* @param string $dn
* @param iterable|array|ModificationInterface[] $modifications
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think iterable|ModificationInterface[] is sufficient here. the indent is a bit off though

@nicolas-grekas nicolas-grekas added this to the next milestone Apr 29, 2018
Copy link
Member

@nicolas-grekas nicolas-grekas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here are some minor comments
ping @csarrazi since you're our LDAP referent :)

@@ -62,4 +63,12 @@ public function rename(Entry $entry, $newRdn, $removeOldRdn = true);
* @throws LdapException
*/
public function remove(Entry $entry);

/**
* @param string $dn
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be removed (duplicates the signature


/**
* @param string $dn
* @param iterable|array|ModificationInterface[] $modifications
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need for "array"

* @param string $dn
* @param iterable|array|ModificationInterface[] $modifications
*
* @return bool
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

conflicts with :void

*
* @return bool
*
* @throws LdapException
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hinting when would be great

* @param string $dn
* @param iterable|array|ModificationInterface[] $modifications
*
* @return bool
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(see previous comments that apply to this docblock also)

}

if (!@ldap_modify_batch($this->getConnectionResource(), $dn, $modificationsMapped)) {
throw new LdapException(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be on one line


if (!@ldap_modify_batch($this->getConnectionResource(), $dn, $modificationsMapped)) {
throw new LdapException(
sprintf('Could execute batch modification on "%s": %s', $dn, ldap_error($this->getConnectionResource()))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could not?
& missing dot at end of message

private function assertValidModificationType(int $type): void
{
if (!in_array($type, $this->validModificationTypes, true)) {
throw new LdapException(sprintf('%s is not a valid modification type.', $type));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing double quotes around %s

LDAP_MODIFY_BATCH_REPLACE,
);

public function __construct($modificationType, string $attribute, array $values = null)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing type hint on $modificationType?

interface ModificationInterface
{
/**
* @return array
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be removed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean the whole Interface or only the docblock?

@mablae
Copy link
Contributor Author

mablae commented Apr 29, 2018

@nicolas-grekas Thanks for your feedback. I will correct these spots. Sorry for steeling your time with inconsistent Docblocks.

I was not sure about introducing the ModificationInterface at all. Maybe that's over engineered?

@csarrazi
Copy link
Contributor

I'm really not fond of adding new methods to EntryManagerInterface, especially since this method is a direct 1:1 conversion of the PHP extension's ldap_modify_batch function.

I'm absolutely not against adding new methods directly to the ExtLdap's EntryManager, but that method should not be in the global EntryManager interface (especially since this is also a breaking change), as this leaks PHP's poorly designed LDAP extension. The whole point of the component is to hide that logic.

Also, I would also remove the ModificationInterface, as it is only used by the extension.
We will design something better, and more flexible in later versions of the component. I would also change the name of the Modification class to something more specific, like UpdateOperation as, the batch operations actually only update a single entry's attribute, in an atomic way, and rename modifyBatch() to applyOperations().

I feel that in the long term, would should use theupdate(Entry $entry) to apply a change set for a given entry. The Entry class should actually calculate and hold the change set, until changes are be applied with the EM's update(Entry $entry) method. The actual logic behind the update would then be completely hidden from the implementation details.

That was actually the design that I wished for at first, but this was never done due to time constraints.

@mablae
Copy link
Contributor Author

mablae commented Apr 30, 2018

I'm really not fond of adding new methods to EntryManagerInterface, especially since this method is a direct 1:1 conversion of the PHP extension's ldap_modify_batch function.

Ok.

I'm absolutely not against adding new methods directly to the ExtLdap's EntryManager, but that method should not be in the global EntryManager interface (especially since this is also a breaking change), as this leaks PHP's poorly designed LDAP extension. The whole point of the component is to hide that logic.

Also, I would also remove the ModificationInterface, as it is only used by the extension.
We will design something better, and more flexible in later versions of the component. I would also change the name of the Modification class to something more specific, like UpdateOperation as, the batch operations actually only update a single entry's attribute, in an atomic way, and rename modifyBatch() to applyOperations().

Is UpdateOperation really a good fit for removal?

I feel that in the long term, would should use theupdate(Entry $entry) to apply a change set for a given entry. The Entry class should actually calculate and hold the change set, until changes are be applied with the EM's update(Entry $entry) method. The actual logic behind the update would then be completely hidden from the implementation details.

That was actually the design that I wished for at first, but this was never done due to time constraints.

I also thought about this direction but it will be much more work, like UnitOfWork state management, correct?

What to do? Simplify the current approach like you suggested or close the PR for the moment?

Thanks for your review!

@csarrazi
Copy link
Contributor

Keep the current approach for now, just remove the method from the interface.

Regarding UpdateOperation, the remove is only applied to a single attribute value, or all values for a single attribute, but this is in reality a form of update.

In LDAP, entries are the first class objects. Attributes are directly embedded within an entry, which means that all these operations (add, remove, remove_all, update) are actually all part of the same update.

@mablae
Copy link
Contributor Author

mablae commented Apr 30, 2018

In LDAP, entries are the first class objects. Attributes are directly embedded within an entry, which means that all these operations (add, remove, remove_all, update) are actually all part of the same update.

Okay, thanks! I will update the PR tonight.

@mablae mablae changed the title [LDAP] Add modifyBatch method to EntryManager [LDAP] Add "applyOperations" method to EntryManager Apr 30, 2018
@mablae
Copy link
Contributor Author

mablae commented Apr 30, 2018

@csarrazi I updated the code as you have suggested.

Test Results because LDAP is not covered by Travis:

image

I have used an openldap docker image for testing and pointed the bootstrap directory to the fixtures.
Worked like a charm after removing the root org from base.ldif which was already created by the docker image: https://gist.github.com/mablae/f23cc8d715c8b2a1de23a656b1fe8499

@csarrazi How do you run the tests? Maybe including this docker stuff in Tests makes sense?

@csarrazi
Copy link
Contributor

@mablae You can use the csarrazi/symfony-ldap Docker container, if you want to test easily :)

This is what I actually run for testing on my end:

docker run -d --name ldap -p 3389:389 \
    -v "/Users/csarrazi/Projects/csarrazi/symfony/src/Symfony/Component/Ldap/Tests/Fixtures/data:/init-ldap.d" \
    -e "LDAP_SUFFIX=dc=symfony,dc=com" \
    -e "LDAP_ROOTDN=cn=admin,dc=symfony,dc=com" \
    -e "LDAP_ROOTPW=symfony" \
    csarrazi/symfony-ldap

@mablae mablae force-pushed the feature-ldap-batch branch from fcfc95e to ed180f4 Compare April 30, 2018 19:27
*
* @throws UpdateOperationException in case of an error
*/
public function applyOperations(string $dn, iterable $modifications): void
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$operations

*/
public function applyOperations(string $dn, iterable $modifications): void
{
$modificationsMapped = array();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$mappedOperations

public function applyOperations(string $dn, iterable $modifications): void
{
$modificationsMapped = array();
foreach ($modifications as $modification) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$operations as $operation

@mablae
Copy link
Contributor Author

mablae commented May 1, 2018

Docs PR added, too

@mablae
Copy link
Contributor Author

mablae commented May 3, 2018

From my side it's ready, what do you think, @csarrazi ?

@csarrazi
Copy link
Contributor

csarrazi commented May 4, 2018

LGTM. Sorry for the late answer, the week has been pretty busy, as always :)

@mablae
Copy link
Contributor Author

mablae commented May 9, 2018

Someone please remove "Need work" in that case. 😄 If anything is missing or can made better just let me know. We even have still some time until 4.2 to make better.

@csarrazi
Copy link
Contributor

Ping @nicolas-grekas

Copy link
Member

@fabpot fabpot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with some minor comments (mainly CS)

/**
* @param int $operationType An LDAP_MODIFY_BATCH_* constant
* @param string $attribute The attribute to batch modify on
* @param array|null $values
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This @param can be removed (as it does not add anything that is not already in the signature)


/**
* @param string $dn Distinguished name to apply operations on
* @param iterable|UpdateOperation[] $operations An array or iterable of Modification instances
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose that Modification should be UpdateOperation here.

@@ -121,4 +122,22 @@ private function getConnectionResource()

return $this->connection->getResource();
}

/**
* @param string $dn Distinguished name to apply operations on
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this one can be removed. $dn in this context is pretty clear.

Also introduce new UpdateOperation class.
@mablae mablae force-pushed the feature-ldap-batch branch from 40b19f6 to 8fc09c7 Compare May 13, 2018 12:11
@mablae
Copy link
Contributor Author

mablae commented May 13, 2018

Thanks @fabpot !

I have updated the code according to your suggestions and rebased/squashed it against current master.

@fabpot
Copy link
Member

fabpot commented May 18, 2018

Thank you @mablae.

@fabpot fabpot merged commit 8fc09c7 into symfony:master May 18, 2018
fabpot added a commit that referenced this pull request May 18, 2018
…ablae)

This PR was merged into the 4.2-dev branch.

Discussion
----------

[LDAP] Add "applyOperations" method to EntryManager

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #27039
| License       | MIT
| Doc PR        | symfony/symfony-docs#9715

This PR adds a new method called `applyOperations` to the LDAP `EntryManager` class.
Internally it is mapping the new `UpdateOperation` object to the `ldap_modify_batch` method.

Tests green against openldap.

Thanks for any feedback.

Todo:

  * [x] Add Docs PR

Commits
-------

8fc09c7 Add applyOperations batch method to EntryManager
mablae added a commit to mablae/symfony-docs that referenced this pull request May 19, 2018
javiereguiluz added a commit to symfony/symfony-docs that referenced this pull request May 22, 2018
This PR was merged into the master branch.

Discussion
----------

[LDAP] Add docs for applyOperations method

See PR symfony/symfony#27069

Commits
-------

74fed75 [LDAP] Add docs for applyOperations method
@nicolas-grekas nicolas-grekas modified the milestones: next, 4.1 Nov 1, 2018
This was referenced Nov 3, 2018
@mablae mablae deleted the feature-ldap-batch branch December 13, 2018 03:25
Guikingone pushed a commit to Guikingone/symfony-docs that referenced this pull request Feb 12, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants