Skip to content

Commit 535ea39

Browse files
committed
Enhance timestamp handling for single item workflows; address #22
1 parent bc9e8cf commit 535ea39

File tree

5 files changed

+66
-7
lines changed

5 files changed

+66
-7
lines changed

rootfs/var/www/leaf-isle-bagger/drupal/api.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,14 @@ def get_node_by_format(session, server, item_id):
6565
)
6666
response.raise_for_status()
6767
return response
68+
69+
def media_associated_with_node_endpoint(id):
70+
return f"node/{id}/media?_format=json"
71+
72+
#
73+
def get_associated_media_by_format(session, server, id):
74+
response = session.get(
75+
urljoin(server, media_associated_with_node_endpoint(id))
76+
)
77+
response.raise_for_status()
78+
return response

rootfs/var/www/leaf-isle-bagger/drupal/utilities.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,29 @@ def id_list_from_arg(session, args):
6060
return node_list
6161

6262

63+
# Query Media because media updates are not reflected in associated Node change timestamps
64+
# exclude Drupal Media not attached to a Drupal Node
65+
# Apply only to the single node case
66+
def single_node_merge_with_media(session, server, node_list, node_id):
67+
68+
try:
69+
node_id = node_id if isinstance(node_id, int) else int(node_id)
70+
except ValueError:
71+
logging.error(f"Invalid node id {node_id}")
72+
else:
73+
# Get assocaiated Media
74+
associated_media_json = drupalApi.get_associated_media_by_format(session, server, node_id)
75+
associated_media = json.loads(associated_media_json.content)
76+
for media in associated_media:
77+
media_changed = media["changed"][0]["value"] if ("changed" in media) else None
78+
node = node_list.get(node_id, None)
79+
if media_changed is not None and node is not None and node["changed"] < media_changed:
80+
# media changed but the parent node did not change
81+
node_list[node_id]["changed"] = media_changed
82+
logging.info(f" Updating node list changed date : {node_list}")
83+
84+
85+
6386
# query media as media changes are not reflected as node revisions
6487
# exclude Drupal Media not attached to a Drupal Node
6588
def id_list_merge_with_media(session, args, node_list):

rootfs/var/www/leaf-isle-bagger/leaf-bagger.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,18 +80,23 @@ def process(args, session):
8080
# a list of resources to preserve
8181
node_list = {}
8282

83+
# get a list of Drupal Node IDs either from specified ID or via a list
8384
if args.force_single_node:
8485
node_list = drupalUtilities.id_list_from_arg(session, args)
85-
logging.info(node_list)
86+
logging.info(f"AIP: Drupal node before media inclusion - {node_list}")
87+
# inspect associated Drupal Media for changes
88+
# a Media change does not transitively update the associated Node change timestamp
89+
# if Media changed but not the associated Node then add associated Node ID to the list
90+
drupalUtilities.single_node_merge_with_media(session, args.server, node_list, args.force_single_node)
91+
logging.info(f"AIP: Drupal node with media changes - {node_list}")
8692
else:
8793
# get a list of Drupal Node IDs changed since a given optional date
8894
# or a single node then force update
8995
node_list = drupalUtilities.id_list_from_nodes(session, args)
9096
logging.info(f"AIP: Drupal nodes before media inclusion - {node_list}")
91-
92-
# inspect Drupal Media for changes
93-
# a Media change is does not transitively change the associated Node change timestamp)
94-
# if Media changed then add associated Node ID to the list
97+
# inspect associated Drupal Media for changes
98+
# a Media change does not transitively update the associated Node change timestamp)
99+
# if Media changed but not the associated Node then add associated Node ID to the list
95100
drupalUtilities.id_list_merge_with_media(session, args, node_list)
96101
logging.info(f"AIP: Drupal nodes with media changes - {node_list}")
97102

rootfs/var/www/leaf-isle-bagger/swift/utilities.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,8 @@ def validate(node_list, swift_container):
9393
):
9494
logging.error(
9595
(
96-
f"id:[{aip_id}] - mismatched modification timestamp [{src_value['changed']}]"
97-
f" : {dst['headers']['x-object-meta-last-mod-timestamp']}"
96+
f"id:[{aip_id}] - mismatched modification timestamp local[{src_value['changed']}]"
97+
f" : swift[{dst['headers']['x-object-meta-last-mod-timestamp']}]"
9898
)
9999
)
100100
break

rootfs/var/www/leaf-isle-bagger/tests/test_drupal.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,3 +152,23 @@ def test_drupal_node_change_without_media(mocker):
152152
drupalUtilities.id_list_merge_with_media(_session, args, node_list)
153153
assert node_list[1]
154154
assert node_list[1]["changed"] == "2025-01-02"
155+
156+
157+
# Test the update of a single node with associated media
158+
# test that the date list captures the media date not the node date
159+
def test_drupal_node_change_without_media(mocker):
160+
node_id = 9999
161+
node_list = {9999: {'changed': '2022-05-18T13:35:49+00:00', 'content_type': 'application/zip'}}
162+
mocker.patch(
163+
"argparse.ArgumentParser.parse_args",
164+
return_value=argparse.Namespace(force_single_node=node_id, server="http://example.com"),
165+
)
166+
args = argparse.ArgumentParser.parse_args()
167+
_adapter.register_uri(
168+
"GET",
169+
f"{args.server}/{drupalApi.media_associated_with_node_endpoint(node_id)}",
170+
text='[ { "changed": [{"value": "2022-05-18T13:35:52+00:00"}], "field_media_of": [{"target_id": 9999}] } ]',
171+
)
172+
drupalUtilities.single_node_merge_with_media(_session, args.server, node_list, args.force_single_node)
173+
assert node_list[node_id]
174+
assert node_list[node_id]["changed"] == "2022-05-18T13:35:52+00:00"

0 commit comments

Comments
 (0)