-
Notifications
You must be signed in to change notification settings - Fork 34
Expand file tree
/
Copy pathclass-delete-sync.php
More file actions
133 lines (118 loc) · 4.12 KB
/
class-delete-sync.php
File metadata and controls
133 lines (118 loc) · 4.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
<?php
/**
* Delete Sync to Cloudinary.
*
* @package Cloudinary
*/
namespace Cloudinary\Sync;
use Cloudinary\Sync;
use Cloudinary\Utils;
/**
* Class Delete_Sync.
*
* Push media to Cloudinary on upload.
*/
class Delete_Sync {
/**
* Holds the plugin instance.
*
* @since 0.1
*
* @var \Cloudinary\Plugin Instance of the global plugin.
*/
protected $plugin;
/**
* Delete_Sync constructor.
*
* @param \Cloudinary\Plugin $plugin The plugin.
*/
public function __construct( \Cloudinary\Plugin $plugin ) {
$this->plugin = $plugin;
}
/**
* Register any hooks that this component needs.
*/
private function register_hooks() {
add_action( 'delete_attachment', array( $this, 'delete_asset' ), 10 );
add_filter( 'user_has_cap', array( $this, 'can_delete_asset' ), 10, 3 );
}
/**
* Checks if an image is synced before allowing a user to have rights to delete the file.
*
* @param array $all_caps All capabilities for the user.
* @param array $caps Current requested capabilities.
* @param array $args Additional args for the check.
*
* @return array
*/
public function can_delete_asset( $all_caps, $caps, $args ) {
if ( 3 === count( $args ) ) {
// The args are indexed, list them in named variables to better understand.
list( $request_cap, , $post_id ) = $args;
if ( $this->plugin->components['media']->is_media( $post_id ) && 'delete_post' === $request_cap && ! empty( $all_caps['delete_posts'] ) ) {
// Check if is pending.
if ( ! $this->plugin->components['sync']->is_synced( $post_id ) && $this->plugin->components['sync']->is_pending( $post_id ) ) {
// Check for errors.
$has_error = get_post_meta( $post_id, Sync::META_KEYS['sync_error'], true );
if ( empty( $has_error ) ) {
$all_caps['delete_posts'] = false;
$action = Utils::get_sanitized_text( 'action' );
if ( ! empty( $action ) && 'delete' === $action ) {
wp_die( esc_html__( 'Sorry, you can’t delete an asset until it has fully synced with Cloudinary. Try again once syncing is complete.', 'cloudinary' ) );
}
}
}
}
}
return $all_caps;
}
/**
* Delete an asset on Cloudinary.
*
* @param int $post_id The post id to delete asset for.
*/
public function delete_asset( $post_id ) {
// In some environments, the $post_id is a string, failing ahead on a strict compare.
// For that reason we need to ensure the variable type.
$post_id = absint( $post_id );
if ( $this->plugin->components['sync']->is_synced( $post_id ) ) {
// check if this is not a transformation base image.
$public_id = $this->plugin->components['media']->get_public_id( $post_id, true );
$linked = $this->plugin->components['media']->get_linked_attachments( $public_id );
if ( count( $linked ) > 1 ) {
// There are other attachments sharing this public_id, so skip it.
return;
}
if ( count( $linked ) === 1 && $post_id !== $linked[0] ) {
// Something odd is up. skip it in case.
return;
}
// Next we need to check that the file is in the cloudinary folder.
$path = trim( Utils::pathinfo( $public_id, PATHINFO_DIRNAME ), '.' );
$cloudinary_folder = $this->plugin->settings->get_value( 'cloudinary_folder' );
if ( $cloudinary_folder === $path ) {
$type = $this->plugin->components['media']->get_resource_type( $post_id );
$options = array(
'public_id' => $public_id,
'invalidate' => true, // clear from CDN cache as well.
);
// Not a background request, since the post could be deleted before the background request hits causing it to not find the post and therefore not finding the public_id
// using the public_id directly in a background call, would make validation complicated since there is no longer a post to validate against.
$this->plugin->components['connect']->api->destroy( $type, $options );
}
/**
* Action fired when deleting a synced asset.
*
* @hook cloudinary_delete_asset
* @since 3.0.1
*/
do_action( 'cloudinary_delete_asset', $post_id );
}
}
/**
* Setup this component.
*/
public function setup() {
$this->register_hooks();
}
}