Skip to content

Commit 302f71e

Browse files
author
Blair McKenzie
committed
image cuts reset tool
1 parent 1fb160f commit 302f71e

4 files changed

Lines changed: 522 additions & 0 deletions

File tree

customadmin/customadmin.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
<subsection id="coapi">
55
<menu id="diagnostics">
66
<menuitem id="cloudinarymigrator" sequence="100" label="Cloudinary Migrator" link="/admin/customadmin.cfm?plugin=cloudinary&amp;module=utilities/cloudinarymigrator.cfm" />
7+
<menuitem id="cloudinaryreset" sequence="101" label="Cloudinary Reset" link="/admin/customadmin.cfm?plugin=cloudinary&amp;module=utilities/cloudinaryreset.cfm" />
78
</menu>
89
</subsection>
910
</section>
Lines changed: 340 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,340 @@
1+
<cfsetting enablecfoutputonly="true" />
2+
<!--- @@displayname: CDN Migration Tool --->
3+
4+
<cfimport taglib="/farcry/core/tags/admin" prefix="admin" />
5+
<cfimport taglib="/farcry/core/tags/formtools" prefix="ft" />
6+
<cfimport taglib="/farcry/core/tags/webskin" prefix="skin" />
7+
8+
9+
<cfif isdefined("url.reset_typename") and isdefined("url.reset_typename") and isdefined("url.reset_property")>
10+
11+
<cfset stResult = structnew() />
12+
<cfset stResult["typename"] = url.reset_typename />
13+
<cfset stResult["objectid"] = url.reset_objectid />
14+
<cfset stResult["property"] = url.reset_property />
15+
16+
<cfset stObj = application.fapi.getContentObject(typename=url.reset_typename,objectid=url.reset_objectid) />
17+
18+
<cfif application.fapi.getPropertyMetadata(url.reset_typename, url.reset_property, "ftType", "") eq "image" and len(application.fapi.getPropertyMetadata(url.reset_typename, url.reset_property, "ftSourceField", ""))>
19+
<cfset sourceField = listfirst(application.fapi.getPropertyMetadata(url.reset_typename, url.reset_property, "ftSourceField"),":") />
20+
<cfset stFP = {} />
21+
<cfset stFP[sourceField] = {
22+
value = stObj[sourceField]
23+
} />
24+
<cfset stFP[url.reset_property] = structnew() />
25+
<cfset oldVal = stObj[url.reset_property] />
26+
<cfset stObj[url.reset_property] = "" />
27+
28+
<cftry>
29+
<cfset stObj = application.formtools.image.oFactory.ImageAutoGenerateBeforeSave(typename=stObj.typename,stProperties=stObj,stFields=application.stCOAPI[url.reset_typename].stProps,stFormPost=stFP) />
30+
31+
<cfif stObj[url.reset_property] neq oldVal>
32+
<cfset application.fapi.setData(stProperties=stObj) />
33+
</cfif>
34+
35+
<cfset stResult["success"] = true />
36+
<cfset stResult["file"] = stObj[url.reset_property] />
37+
38+
<cfcatch>
39+
<cfset stResult["success"] = false />
40+
<cfset stResult["error"] = cfcatch.message />
41+
</cfcatch>
42+
</cftry>
43+
</cfif>
44+
45+
<cfcontent type="text/json" variable="#ToBinary( ToBase64( serializeJSON(stResult) ) )#" reset="Yes">
46+
</cfif>
47+
48+
49+
<cfparam name="form.copy" default="missing" />
50+
<cfparam name="form.step" default="select-type" />
51+
52+
53+
<admin:header>
54+
55+
<cfif form.step eq "select-type">
56+
<cfset qTypes = querynew("typename,typelabel,properties") />
57+
58+
<cfloop collection="#application.stCOAPI#" item="thistype">
59+
<cfif listcontains("type,rule",application.stCOAPI[thistype].class)>
60+
<cfloop collection="#application.stCOAPI[thistype].stProps#" item="thisprop">
61+
<cfif application.fapi.getPropertyMetadata(thistype, thisprop, "ftType", "string") eq "image" and len(application.fapi.getPropertyMetadata(thistype, thisprop, "ftSourceField", ""))>
62+
<cfif qTypes.typename[qTypes.recordcount] neq thistype>
63+
<cfset queryaddrow(qTypes) />
64+
</cfif>
65+
66+
<cfset querysetcell(qTypes,"typename",thistype) />
67+
<cfset querysetcell(qTypes,"typelabel",application.stCOAPI[thistype].displayname) />
68+
<cfset querysetcell(qTypes,"properties",listappend(qTypes.properties[qTypes.recordcount],application.fapi.getPropertyMetadata(thistype, thisprop, "ftLabel", thisprop))) />
69+
</cfif>
70+
</cfloop>
71+
</cfif>
72+
</cfloop>
73+
74+
<cfquery dbtype="query" name="qTypes">
75+
select * from qTypes order by typelabel
76+
</cfquery>
77+
78+
<skin:htmlHead><cfoutput>
79+
<style>
80+
.selected, .selected td { background-color:##F9E6D4; }
81+
th.select, td.select { width:40px; }
82+
th.insource, td.insource, th.intarget, td.intarget { width:80px; }
83+
##files th.insource, td.insource { text-align:right; }
84+
td.insource, td.intarget, td.status { font-weight:bold; }
85+
.in-location-Yes { color:##01a100; }
86+
.in-location-No { color:##FF0000; }
87+
th.status, td.status { width:80px; }
88+
.status-not-applicable { color:##666666; }
89+
.status-success { color:##01a100; }
90+
.status-failure { color:##FF0000; }
91+
</style>
92+
</cfoutput></skin:htmlHead>
93+
94+
<cfoutput>
95+
<h1><admin:resource key="webtop.utilities.cdnmigrator@title">Cloudinary Reset Tool</admin:resource></h1>
96+
<admin:resource key="webtop.utilities.coapisqllog.blurb@html">
97+
<p>This tool makes it easy to reset stored Cloudinary URLs.</p>
98+
</admin:resource>
99+
</cfoutput>
100+
101+
<ft:form>
102+
<ft:buttonPanel>
103+
<ft:button value="Select Types" />
104+
</ft:buttonPanel>
105+
106+
<cfoutput><input type="hidden" name="step" value="review-files"></cfoutput>
107+
108+
<ft:field label="Types" bMultiField="true" class="blockLabels">
109+
<cfoutput>
110+
<table id="files" class="objectAdmin" style="width:100%;table-layout:fixed;">
111+
<thead>
112+
<tr>
113+
<th class="select"></th>
114+
<th class="type">Type</th>
115+
<th class="property">Properties</th>
116+
</tr>
117+
</thead>
118+
<tbody>
119+
</cfoutput>
120+
121+
<cfoutput query="qTypes">
122+
<tr id="type-#qTypes.currentrow#" class="type <cfif qTypes.currentrow mod 2>alt</cfif>">
123+
<td class="select"><input type="checkbox" name="types" value="#qTypes.typename#"></td>
124+
<td class="type">#qTypes.typelabel#</td>
125+
<td class="property">#replace(qTypes.properties,",",", ","ALL")#</td>
126+
</tr>
127+
</cfoutput>
128+
129+
<cfoutput>
130+
</tbody>
131+
</table>
132+
</cfoutput>
133+
134+
<ft:buttonPanel>
135+
<ft:button value="Select Types" />
136+
</ft:buttonPanel>
137+
</ft:field>
138+
</ft:form>
139+
140+
<cfelseif form.step eq "review-files">
141+
<cfset qWrong = querynew("typename,typelabel,property,seq,objectid,label,filename","varchar,varchar,varchar,integer,varchar,varchar,varchar") />
142+
143+
<cfloop collection="#application.stCOAPI#" item="thistype">
144+
<cfif listfindnocase(form.types,thistype) and listcontains("type,rule",application.stCOAPI[thistype].class)>
145+
<cfloop collection="#application.stCOAPI[thistype].stProps#" item="thisprop">
146+
<cfif application.fapi.getPropertyMetadata(thistype, thisprop, "ftType", "string") eq "image" and len(application.fapi.getPropertyMetadata(thistype, thisprop, "ftSourceField", ""))>
147+
<cfset o = application.fapi.getContentType(typename=thistype) />
148+
<cfquery datasource="#application.dsn#" name="q">
149+
select objectid,label,#thisprop#
150+
from #application.dbowner##thistype#
151+
</cfquery>
152+
153+
<cfloop query="q">
154+
<cfset queryaddrow(qWrong) />
155+
<cfset querysetcell(qWrong,"typename",thistype) />
156+
<cfset querysetcell(qWrong,"typelabel",application.stCOAPI[thistype].displayname) />
157+
<cfset querysetcell(qWrong,"property",thisprop) />
158+
<cfset querysetcell(qWrong,"seq",application.stCOAPI[thistype].stProps[thisprop].metadata.ftSeq) />
159+
<cfset querysetcell(qWrong,"objectid",q.objectid) />
160+
<cfset querysetcell(qWrong,"label",q.label) />
161+
<cfset querysetcell(qWrong,"filename",q[thisprop][q.currentrow]) />
162+
</cfloop>
163+
</cfif>
164+
</cfloop>
165+
</cfif>
166+
</cfloop>
167+
168+
<cfquery dbtype="query" name="qWrong">
169+
select *
170+
from qWrong
171+
order by typelabel, property, label, objectid, seq
172+
</cfquery>
173+
174+
<skin:htmlHead><cfoutput>
175+
<style>
176+
.selected, .selected td { background-color:##F9E6D4; }
177+
th.select, td.select { width:40px; }
178+
th.insource, td.insource, th.intarget, td.intarget { width:80px; }
179+
##files th.insource, td.insource { text-align:right; }
180+
td.insource, td.intarget, td.status { font-weight:bold; }
181+
.in-location-Yes { color:##01a100; }
182+
.in-location-No { color:##FF0000; }
183+
th.status, td.status { width:80px; }
184+
.status-not-applicable { color:##666666; }
185+
.status-success { color:##01a100; }
186+
.status-failure { color:##FF0000; }
187+
</style>
188+
<script type="text/javascript">
189+
var processing = false;
190+
var processingfile = -1;
191+
192+
function getNextFile(){
193+
var file = $j("##files tbody input[name=files]:checked").first().parents("tr");
194+
195+
if (file.size()){
196+
return file.data("file") - 1;
197+
}
198+
else{
199+
return -1;
200+
}
201+
}
202+
203+
function copyFiles(action){
204+
if (action==="toggle" && processing && processingfile>-1){
205+
processing = false;
206+
}
207+
else if ((action==="next" && processing) || (action==="toggle" && !processing)){
208+
processing = true;
209+
processingfile = getNextFile();
210+
211+
if (processingfile>-1){
212+
var info = $j("##file-"+(processingfile+1)+" input").val().split("|");
213+
$j.getJSON("#application.fapi.fixURL()#&reset_typename="+info[0]+"&reset_objectid="+info[1]+"&reset_property="+info[2],function(data){
214+
if (data.success){
215+
$j("##file-"+(processingfile+1))
216+
.removeClass("selected")
217+
.find("input[name=files]").attr("checked",null).end()
218+
.find(".status").removeClass("status-not-applicable").removeClass("status-success").removeClass("status-failure").addClass("status-success").html("Done").attr("title","").end()
219+
.find(".file").html(data.file);
220+
}
221+
else{
222+
$j("##file-"+(processingfile+1))
223+
.removeClass("selected")
224+
.find("input[name=files]").attr("checked",null).end()
225+
.find(".status").removeClass("status-not-applicable").removeClass("status-success").removeClass("status-failure").addClass("status-failure").html("Error").attr("title",data.error).end();
226+
}
227+
228+
copyFiles("next");
229+
});
230+
}
231+
else{
232+
processing = false;
233+
}
234+
}
235+
};
236+
</script>
237+
</cfoutput>
238+
<skin:onReady><cfoutput>
239+
$j("##allfiles").click(function(){
240+
var tr = $j("##files tbody input[name=files]").attr("checked",$j(this).attr("checked")==="checked"?"checked":null).parents("tr.file");
241+
242+
if ($j(this).attr("checked")==="checked")
243+
tr.addClass("selected");
244+
else
245+
tr.removeClass("selected")
246+
});
247+
$j("##files tbody tr").click(function(event){
248+
var target = $j(event.target), input = $j("input[name=files]",this), self = $j(this);
249+
250+
if (!target.is("input"))
251+
input.attr("checked",input.attr("checked")==="checked"?null:"checked");
252+
253+
if (input.attr("checked") === "checked")
254+
self.addClass("selected");
255+
else
256+
self.removeClass("selected");
257+
});
258+
</cfoutput></skin:onReady>
259+
260+
<cfoutput>
261+
<h1><admin:resource key="webtop.utilities.cdnmigrator@title">Cloudinary Reset Tool</admin:resource></h1>
262+
<admin:resource key="webtop.utilities.coapisqllog.blurb@html">
263+
<p>This tool makes it easy to reset stored Cloudinary URLs.</p>
264+
</admin:resource>
265+
</cfoutput>
266+
267+
<ft:form>
268+
<ft:buttonPanel>
269+
<cfif qWrong.recordcount>
270+
<ft:button value="Reset URLs" onclick="copyFiles('toggle');return false;" />
271+
</cfif>
272+
</ft:buttonPanel>
273+
274+
<cfif qWrong.recordcount>
275+
<ft:field label="Files" bMultiField="true" class="blockLabels">
276+
<cfoutput>
277+
<table id="files" class="objectAdmin" style="width:100%;table-layout:fixed;">
278+
<thead>
279+
<tr>
280+
<th class="select"><input type="checkbox" id="allfiles"></th>
281+
<th class="type">Type</th>
282+
<th class="property">Property</th>
283+
<th class="title">Object</th>
284+
<th class="file">File</th>
285+
<th class="status">Status</th>
286+
</tr>
287+
</thead>
288+
<tbody>
289+
</cfoutput>
290+
291+
<cfoutput query="qWrong">
292+
<tr id="file-#qWrong.currentrow#" class="file <cfif qWrong.currentrow mod 2>alt</cfif>" data-typename="#qWrong.typename#" data-property="#qWrong.property#" data-file="#qWrong.currentrow#">
293+
<td class="select"><input type="checkbox" name="files" value="#qWrong.typename#|#qWrong.objectid#|#qWrong.property#"></td>
294+
<td class="type">#qWrong.typelabel# (<a class="select-by-typename" data-typename="#qWrong.typename#">select all</a>)</td>
295+
<td class="property">#qWrong.property# (<a class="select-by-property" data-typename="#qWrong.typename#" data-property="#qWrong.property#">select all</a>)</td>
296+
<td class="title">#qWrong.label#</td>
297+
<td class="file">#qWrong.filename#</td>
298+
<td class="status status-not-applicable">N/A</td>
299+
</tr>
300+
</cfoutput>
301+
302+
<cfoutput>
303+
</tbody>
304+
</table>
305+
<script>
306+
$j(".select-by-typename").bind("click",function(e){
307+
var self = $j(this);
308+
var typename = self.data("typename");
309+
310+
$j('tr[data-typename='+typename+'] input[type=checkbox]')
311+
.prop('checked',true);
312+
313+
e.stopPropagation();
314+
e.preventDefault();
315+
});
316+
$j(".select-by-property").bind("click",function(e){
317+
var self = $j(this);
318+
var typename = self.data("typename");
319+
var property = self.data("property");
320+
321+
$j('tr[data-typename='+typename+'][data-property='+property+'] input[type=checkbox]')
322+
.prop('checked',true);
323+
324+
e.stopPropagation();
325+
e.preventDefault();
326+
});
327+
</script>
328+
</cfoutput>
329+
</ft:field>
330+
331+
<ft:buttonPanel>
332+
<ft:button value="Copy Files" onclick="copyFiles('toggle');return false;" />
333+
</ft:buttonPanel>
334+
</cfif>
335+
</ft:form>
336+
</cfif>
337+
338+
<admin:footer>
339+
340+
<cfsetting enablecfoutputonly="false" />

packages/formtools/image.cfc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,8 @@
235235
<cfif refind("\?(source|_source)=",sourcefilename)>
236236
<cfreturn passed(rereplace(sourcefilename,"\?_?source=[^&]+","") & "?_source=" & getCloudinarySource(sourcefilename)) />
237237
</cfif>
238+
<cfelseif len(sourcefilename) and application.fc.lib.cdn.ioFileExists(location="images",file=sourcefilename)>
239+
<cfset sourcefilename = application.fc.lib.cdn.ioCopyFile(source_location="images",source_file=sourcefilename,dest_location="images",dest_file=arguments.destination & "/" & listlast(sourcefilename,"\/"),nameconflict="makeunique",uniqueamong="images") />
238240
</cfif>
239241

240242
<cfreturn passed(sourcefilename) />

0 commit comments

Comments
 (0)