Version 2(add Google_Service_Drive )
This commit is contained in:
parent
747c6e8a44
commit
c522954b44
|
|
@ -1,3 +1,3 @@
|
||||||
/node_modules
|
/node_modules
|
||||||
|
config/service-account.json
|
||||||
package-lock.json
|
package-lock.json
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
width: 100px;
|
width: 100px;
|
||||||
height: 100px;
|
height: 100px;
|
||||||
background-image: url('../img/microphone.png'); /* آدرس تصویر میکروفون */
|
background-image: url("../img/microphone.png"); /* آدرس تصویر میکروفون */
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
background-size: 50%;
|
background-size: 50%;
|
||||||
|
|
@ -68,7 +68,7 @@
|
||||||
background-color: #f4f4f9;
|
background-color: #f4f4f9;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
|
||||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
|
||||||
color: #333;
|
color: #333;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -153,3 +153,118 @@
|
||||||
border-top: 2px solid #0073aa;
|
border-top: 2px solid #0073aa;
|
||||||
background-color: #f2f2f2;
|
background-color: #f2f2f2;
|
||||||
}
|
}
|
||||||
|
.audio-diary-admin-list-page {
|
||||||
|
max-width: 900px;
|
||||||
|
margin: 20px auto;
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||||
|
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.audio-diary-admin-list-page h1 {
|
||||||
|
font-size: 26px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
color: #2c3e50;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-buttons {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
padding: 10px 20px;
|
||||||
|
font-size: 14px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
background-color: #0073aa;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.btn-primary:hover {
|
||||||
|
background-color: #005177;
|
||||||
|
}
|
||||||
|
.btn-danger {
|
||||||
|
background-color: #e74c3c;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.btn-danger:hover {
|
||||||
|
background-color: #c0392b;
|
||||||
|
}
|
||||||
|
.btn-secondary {
|
||||||
|
background-color: #7f8c8d;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.btn-secondary:hover {
|
||||||
|
background-color: #6c757d;
|
||||||
|
}
|
||||||
|
.btn-small {
|
||||||
|
padding: 6px 12px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-upload {
|
||||||
|
background-color: #27ae60;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.btn-upload:hover {
|
||||||
|
background-color: #219653;
|
||||||
|
}
|
||||||
|
.btn-upload.uploaded {
|
||||||
|
background-color: #95a5a6;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selected-count {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #7f8c8d;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
th,
|
||||||
|
td {
|
||||||
|
border: 1px solid #e0e0e0;
|
||||||
|
padding: 12px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
background-color: #34495e;
|
||||||
|
color: white;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr:nth-child(even) {
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
}
|
||||||
|
tr:hover {
|
||||||
|
background-color: #f1f1f1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-cell {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
audio {
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-audio {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
jQuery(document).ready(function($) {
|
jQuery(document).ready(function ($) {
|
||||||
let mediaRecorder;
|
let mediaRecorder;
|
||||||
let audioChunks = [];
|
let audioChunks = [];
|
||||||
let isRecording = false;
|
let isRecording = false;
|
||||||
let audioContext, analyser, dataArray, bufferLength, source;
|
let audioContext, analyser, dataArray, bufferLength, source;
|
||||||
|
let isVisualizing = false;
|
||||||
|
|
||||||
function visualize(stream) {
|
function visualize(stream) {
|
||||||
audioContext = new (window.AudioContext || window.webkitAudioContext)();
|
audioContext = new (window.AudioContext || window.webkitAudioContext)();
|
||||||
|
|
@ -13,10 +14,11 @@ jQuery(document).ready(function($) {
|
||||||
bufferLength = analyser.frequencyBinCount;
|
bufferLength = analyser.frequencyBinCount;
|
||||||
dataArray = new Uint8Array(bufferLength);
|
dataArray = new Uint8Array(bufferLength);
|
||||||
|
|
||||||
const canvas = document.getElementById('visualizer');
|
const canvas = document.getElementById("visualizer");
|
||||||
const canvasCtx = canvas.getContext('2d');
|
const canvasCtx = canvas.getContext("2d");
|
||||||
|
|
||||||
function draw() {
|
function draw() {
|
||||||
|
if (!isVisualizing) return;
|
||||||
requestAnimationFrame(draw);
|
requestAnimationFrame(draw);
|
||||||
analyser.getByteTimeDomainData(dataArray);
|
analyser.getByteTimeDomainData(dataArray);
|
||||||
|
|
||||||
|
|
@ -26,20 +28,20 @@ jQuery(document).ready(function($) {
|
||||||
canvasCtx.beginPath();
|
canvasCtx.beginPath();
|
||||||
canvasCtx.moveTo(0, centerY);
|
canvasCtx.moveTo(0, centerY);
|
||||||
canvasCtx.lineTo(canvas.width, centerY);
|
canvasCtx.lineTo(canvas.width, centerY);
|
||||||
canvasCtx.strokeStyle = 'rgba(0, 0, 0, 0.2)';
|
canvasCtx.strokeStyle = "rgba(0, 0, 0, 0.2)";
|
||||||
canvasCtx.lineWidth = 1;
|
canvasCtx.lineWidth = 1;
|
||||||
canvasCtx.stroke();
|
canvasCtx.stroke();
|
||||||
|
|
||||||
canvasCtx.lineWidth = 2;
|
canvasCtx.lineWidth = 2;
|
||||||
canvasCtx.strokeStyle = 'rgb(0, 0, 0)';
|
canvasCtx.strokeStyle = "rgb(0, 0, 0)";
|
||||||
|
|
||||||
canvasCtx.beginPath();
|
canvasCtx.beginPath();
|
||||||
let sliceWidth = canvas.width * 1.0 / bufferLength;
|
let sliceWidth = (canvas.width * 1.0) / bufferLength;
|
||||||
let x = 0;
|
let x = 0;
|
||||||
|
|
||||||
for (let i = 0; i < bufferLength; i++) {
|
for (let i = 0; i < bufferLength; i++) {
|
||||||
let v = dataArray[i] / 128.0;
|
let v = dataArray[i] / 128.0;
|
||||||
let y = v * canvas.height / 2;
|
let y = (v * canvas.height) / 2;
|
||||||
|
|
||||||
if (i === 0) {
|
if (i === 0) {
|
||||||
canvasCtx.moveTo(x, y);
|
canvasCtx.moveTo(x, y);
|
||||||
|
|
@ -54,300 +56,372 @@ jQuery(document).ready(function($) {
|
||||||
canvasCtx.stroke();
|
canvasCtx.stroke();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isVisualizing = true;
|
||||||
draw();
|
draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showToast(message, type) {
|
||||||
$('#download-zip').on('click', function() {
|
|
||||||
var selectedFiles = [];
|
|
||||||
$('.select-audio:checked').each(function() {
|
|
||||||
selectedFiles.push($(this).val());
|
|
||||||
});
|
|
||||||
|
|
||||||
if (selectedFiles.length > 0) {
|
|
||||||
var form = document.createElement('form');
|
|
||||||
form.method = 'POST';
|
|
||||||
form.action = '';
|
|
||||||
|
|
||||||
selectedFiles.forEach(function(file) {
|
|
||||||
var input = document.createElement('input');
|
|
||||||
input.type = 'hidden';
|
|
||||||
input.name = 'selected_files[]';
|
|
||||||
input.value = file;
|
|
||||||
form.appendChild(input);
|
|
||||||
});
|
|
||||||
|
|
||||||
document.body.appendChild(form);
|
|
||||||
form.submit();
|
|
||||||
} else {
|
|
||||||
$.toast({
|
$.toast({
|
||||||
text: "Please select at least one audio file to download.",
|
text: message,
|
||||||
heading: 'Note',
|
heading: "Note",
|
||||||
icon: 'error',
|
icon: type,
|
||||||
showHideTransition: 'fade',
|
showHideTransition: "fade",
|
||||||
allowToastClose: true,
|
allowToastClose: true,
|
||||||
hideAfter: 3000,
|
hideAfter: 3000,
|
||||||
stack: 3,
|
stack: 3,
|
||||||
position: 'bottom-center',
|
position: "bottom-center",
|
||||||
textAlign: 'left',
|
textAlign: "left",
|
||||||
loader: true,
|
loader: true,
|
||||||
loaderBg: '#FF0000',
|
loaderBg: type === "success" ? "#9EC600" : "#FF0000",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
|
$(".download-single").on("click", function () {
|
||||||
|
var $button = $(this);
|
||||||
|
var fileUrl = $button.data("url");
|
||||||
|
var fileName = $button.data("name");
|
||||||
|
|
||||||
|
var downloadLink = document.createElement("a");
|
||||||
$('#recording-button').on('click', function() {
|
downloadLink.href = fileUrl;
|
||||||
if (!isRecording) {
|
downloadLink.download = fileName;
|
||||||
navigator.mediaDevices.getUserMedia({ audio: true })
|
|
||||||
.then(stream => {
|
|
||||||
mediaRecorder = new MediaRecorder(stream);
|
|
||||||
mediaRecorder.start();
|
|
||||||
visualize(stream);
|
|
||||||
|
|
||||||
mediaRecorder.ondataavailable = function(event) {
|
|
||||||
audioChunks.push(event.data);
|
|
||||||
};
|
|
||||||
|
|
||||||
mediaRecorder.onstop = function() {
|
|
||||||
const audioBlob = new Blob(audioChunks, { type: 'audio/wav' });
|
|
||||||
audioChunks = [];
|
|
||||||
const audioUrl = URL.createObjectURL(audioBlob);
|
|
||||||
$('#audio-player').attr('src', audioUrl).addClass('show');
|
|
||||||
|
|
||||||
let formData = new FormData();
|
|
||||||
formData.append('audio_data', audioBlob, 'audio.wav');
|
|
||||||
formData.append('action', 'save_audio');
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
url: ajaxurl,
|
|
||||||
type: 'POST',
|
|
||||||
data: formData,
|
|
||||||
processData: false,
|
|
||||||
contentType: false,
|
|
||||||
success: function(response) {
|
|
||||||
if (response.success) {
|
|
||||||
$.toast({
|
|
||||||
text: "Audio saved successfully",
|
|
||||||
heading: 'Note',
|
|
||||||
icon: 'success',
|
|
||||||
showHideTransition: 'fade',
|
|
||||||
allowToastClose: true,
|
|
||||||
hideAfter: 3000,
|
|
||||||
stack: 3,
|
|
||||||
position: 'bottom-center',
|
|
||||||
textAlign: 'left',
|
|
||||||
loader: true,
|
|
||||||
loaderBg: '#9EC600',
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
$.toast({
|
|
||||||
text: "Failed to save audio",
|
|
||||||
heading: 'Note',
|
|
||||||
icon: 'error',
|
|
||||||
showHideTransition: 'fade',
|
|
||||||
allowToastClose: true,
|
|
||||||
hideAfter: 3000,
|
|
||||||
stack: 3,
|
|
||||||
position: 'bottom-center',
|
|
||||||
textAlign: 'left',
|
|
||||||
loader: true,
|
|
||||||
loaderBg: '#9EC600',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
$('#visualizer').show();
|
|
||||||
isRecording = true;
|
|
||||||
$('#recording-button').css('background-color', 'green');
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
mediaRecorder.stop();
|
|
||||||
$('#visualizer').hide();
|
|
||||||
isRecording = false;
|
|
||||||
$('#recording-button').css('background-color', 'red');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#download-selected').on('click', function() {
|
|
||||||
let selectedFiles = [];
|
|
||||||
$('.select-audio:checked').each(function() {
|
|
||||||
selectedFiles.push($(this).val());
|
|
||||||
});
|
|
||||||
|
|
||||||
if (selectedFiles.length > 0) {
|
|
||||||
$.ajax({
|
|
||||||
url: ajaxurl,
|
|
||||||
type: 'POST',
|
|
||||||
data: {
|
|
||||||
action: 'download_zip',
|
|
||||||
files: selectedFiles
|
|
||||||
},
|
|
||||||
success: function(response) {
|
|
||||||
if (response.success) {
|
|
||||||
$.toast({
|
|
||||||
text: "Zip file created successfully",
|
|
||||||
heading: 'Note',
|
|
||||||
icon: 'success',
|
|
||||||
showHideTransition: 'fade',
|
|
||||||
allowToastClose: true,
|
|
||||||
hideAfter: 3000,
|
|
||||||
stack: 3,
|
|
||||||
position: 'bottom-center',
|
|
||||||
textAlign: 'left',
|
|
||||||
loader: true,
|
|
||||||
loaderBg: '#9EC600',
|
|
||||||
});
|
|
||||||
|
|
||||||
// ایجاد لینک دانلود
|
|
||||||
let downloadLink = document.createElement('a');
|
|
||||||
downloadLink.href = response.data.zip_url;
|
|
||||||
downloadLink.download = response.data.zip_url.split('/').pop();
|
|
||||||
document.body.appendChild(downloadLink);
|
document.body.appendChild(downloadLink);
|
||||||
downloadLink.click();
|
downloadLink.click();
|
||||||
document.body.removeChild(downloadLink);
|
document.body.removeChild(downloadLink);
|
||||||
|
|
||||||
// برداشتن انتخاب فایلهای صوتی
|
|
||||||
$('.select-audio').prop('checked', false);
|
|
||||||
} else {
|
|
||||||
$.toast({
|
|
||||||
text: "Failed to create zip file: " + response.data,
|
|
||||||
heading: 'Error',
|
|
||||||
icon: 'error',
|
|
||||||
showHideTransition: 'fade',
|
|
||||||
allowToastClose: true,
|
|
||||||
hideAfter: 3000,
|
|
||||||
stack: 3,
|
|
||||||
position: 'bottom-center',
|
|
||||||
textAlign: 'left',
|
|
||||||
loader: true,
|
|
||||||
loaderBg: '#FF0000',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
error: function(jqXHR, textStatus, errorThrown) {
|
|
||||||
console.log('AJAX Error: ' + textStatus + ': ' + errorThrown);
|
|
||||||
$.toast({
|
|
||||||
text: "AJAX Error: " + textStatus + ": " + errorThrown,
|
|
||||||
heading: 'Error',
|
|
||||||
icon: 'error',
|
|
||||||
showHideTransition: 'fade',
|
|
||||||
allowToastClose: true,
|
|
||||||
hideAfter: 3000,
|
|
||||||
stack: 3,
|
|
||||||
position: 'bottom-center',
|
|
||||||
textAlign: 'left',
|
|
||||||
loader: true,
|
|
||||||
loaderBg: '#FF0000',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#select-all').on('click', function() {
|
$("#download-zip").on("click", function () {
|
||||||
let isSelectAll = $(this).data('select-all');
|
var selectedFiles = [];
|
||||||
|
$(".select-audio:checked").each(function () {
|
||||||
if (isSelectAll) {
|
|
||||||
$('.select-audio').prop('checked', true);
|
|
||||||
$(this).text('Unselect All');
|
|
||||||
} else {
|
|
||||||
$('.select-audio').prop('checked', false);
|
|
||||||
$(this).text('Select All');
|
|
||||||
}
|
|
||||||
|
|
||||||
// تغییر حالت دکمه
|
|
||||||
$(this).data('select-all', !isSelectAll);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// حذف فایلهای انتخابشده
|
|
||||||
$('#delete-selected').on('click', function() {
|
|
||||||
let selectedFiles = [];
|
|
||||||
$('.select-audio:checked').each(function() {
|
|
||||||
selectedFiles.push($(this).val());
|
selectedFiles.push($(this).val());
|
||||||
});
|
});
|
||||||
|
|
||||||
if (selectedFiles.length > 0 && confirm("Are you sure you want to delete selected audio files?")) {
|
if (selectedFiles.length > 0) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: ajaxurl,
|
url: ajaxurl,
|
||||||
type: 'POST',
|
type: "POST",
|
||||||
data: {
|
data: {
|
||||||
action: 'delete_selected_audios',
|
action: "download_zip",
|
||||||
files: selectedFiles
|
files: selectedFiles,
|
||||||
},
|
},
|
||||||
success: function(response) {
|
success: function (response) {
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
$.toast({
|
showToast("Zip file created successfully", "success");
|
||||||
text: "Selected audio files deleted successfully",
|
var downloadLink = document.createElement("a");
|
||||||
heading: 'Note',
|
downloadLink.href = response.data.zip_url;
|
||||||
icon: 'success',
|
downloadLink.download = response.data.zip_url.split("/").pop();
|
||||||
showHideTransition: 'fade',
|
document.body.appendChild(downloadLink);
|
||||||
allowToastClose: true,
|
downloadLink.click();
|
||||||
hideAfter: 3000,
|
document.body.removeChild(downloadLink);
|
||||||
stack: 3,
|
$(".select-audio").prop("checked", false);
|
||||||
position: 'bottom-center',
|
} else {
|
||||||
textAlign: 'left',
|
showToast("Failed to create zip file: " + response.data, "error");
|
||||||
loader: true,
|
}
|
||||||
loaderBg: '#9EC600',
|
},
|
||||||
|
error: function (jqXHR, textStatus, errorThrown) {
|
||||||
|
showToast("AJAX Error: " + textStatus + ": " + errorThrown, "error");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
showToast("Please select at least one audio file to download.", "error");
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// پس از حذف موفق فایلها، لیست را بهروزرسانی کنید
|
$("#recording-button").on("click", function () {
|
||||||
selectedFiles.forEach(function(fileName) {
|
if (!isRecording) {
|
||||||
$('.delete-audio[data-file="' + fileName + '"]').closest('tr').fadeOut(400, function() {
|
navigator.mediaDevices
|
||||||
|
.getUserMedia({ audio: true })
|
||||||
|
.then((stream) => {
|
||||||
|
mediaRecorder = new MediaRecorder(stream);
|
||||||
|
audioChunks = [];
|
||||||
|
mediaRecorder.start();
|
||||||
|
visualize(stream);
|
||||||
|
|
||||||
|
mediaRecorder.ondataavailable = function (event) {
|
||||||
|
audioChunks.push(event.data);
|
||||||
|
};
|
||||||
|
|
||||||
|
mediaRecorder.onstop = function () {
|
||||||
|
stream.getTracks().forEach((track) => track.stop());
|
||||||
|
const audioBlob = new Blob(audioChunks, { type: "audio/wav" });
|
||||||
|
audioChunks = [];
|
||||||
|
const audioUrl = URL.createObjectURL(audioBlob);
|
||||||
|
$("#audio-player").attr("src", audioUrl).addClass("show");
|
||||||
|
|
||||||
|
let formData = new FormData();
|
||||||
|
formData.append("audio_data", audioBlob, "audio.wav");
|
||||||
|
formData.append("action", "save_audio");
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: ajaxurl,
|
||||||
|
type: "POST",
|
||||||
|
data: formData,
|
||||||
|
processData: false,
|
||||||
|
contentType: false,
|
||||||
|
success: function (response) {
|
||||||
|
if (response.success) {
|
||||||
|
showToast("Audio saved successfully", "success");
|
||||||
|
} else {
|
||||||
|
showToast("Failed to save audio", "error");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$("#visualizer").show();
|
||||||
|
isRecording = true;
|
||||||
|
$("#recording-button").css("background-color", "green");
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
showToast("Unable to access microphone: " + error.message, "error");
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
mediaRecorder.stop();
|
||||||
|
$("#visualizer").hide();
|
||||||
|
isVisualizing = false;
|
||||||
|
audioContext.close();
|
||||||
|
isRecording = false;
|
||||||
|
$("#recording-button").css("background-color", "red");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#download-selected").on("click", function () {
|
||||||
|
let selectedFiles = [];
|
||||||
|
$(".select-audio:checked").each(function () {
|
||||||
|
selectedFiles.push($(this).val());
|
||||||
|
});
|
||||||
|
|
||||||
|
if (selectedFiles.length > 0) {
|
||||||
|
$.ajax({
|
||||||
|
url: ajaxurl,
|
||||||
|
type: "POST",
|
||||||
|
data: {
|
||||||
|
action: "download_zip",
|
||||||
|
files: selectedFiles,
|
||||||
|
},
|
||||||
|
success: function (response) {
|
||||||
|
if (response.success) {
|
||||||
|
showToast("Zip file created successfully", "success");
|
||||||
|
let downloadLink = document.createElement("a");
|
||||||
|
downloadLink.href = response.data.zip_url;
|
||||||
|
downloadLink.download = response.data.zip_url.split("/").pop();
|
||||||
|
document.body.appendChild(downloadLink);
|
||||||
|
downloadLink.click();
|
||||||
|
document.body.removeChild(downloadLink);
|
||||||
|
$(".select-audio").prop("checked", false);
|
||||||
|
} else {
|
||||||
|
showToast("Failed to create zip file: " + response.data, "error");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function (jqXHR, textStatus, errorThrown) {
|
||||||
|
showToast("AJAX Error: " + textStatus + ": " + errorThrown, "error");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#select-all").on("click", function () {
|
||||||
|
let isSelectAll = $(this).data("select-all");
|
||||||
|
if (isSelectAll) {
|
||||||
|
$(".select-audio").prop("checked", true);
|
||||||
|
$(this).text("Unselect All");
|
||||||
|
} else {
|
||||||
|
$(".select-audio").prop("checked", false);
|
||||||
|
$(this).text("Select All");
|
||||||
|
}
|
||||||
|
$(this).data("select-all", !isSelectAll);
|
||||||
|
});
|
||||||
|
|
||||||
|
// فقط یه رویداد برای #delete-selected
|
||||||
|
$("#delete-selected").on("click", function () {
|
||||||
|
const selectedFiles = [];
|
||||||
|
$(".select-audio:checked").each(function () {
|
||||||
|
selectedFiles.push($(this).val());
|
||||||
|
});
|
||||||
|
|
||||||
|
if (selectedFiles.length === 0) {
|
||||||
|
showToast("Please select at least one audio file to delete.", "error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const confirmDialog = confirm(
|
||||||
|
"Are you sure you want to delete " +
|
||||||
|
selectedFiles.length +
|
||||||
|
" selected file(s)?\nPress OK to delete only locally, or Cancel and choose below."
|
||||||
|
);
|
||||||
|
if (!confirmDialog) {
|
||||||
|
const deleteFromDrive = confirm(
|
||||||
|
"Also delete these files from Google Drive?"
|
||||||
|
);
|
||||||
|
deleteFiles(selectedFiles, deleteFromDrive);
|
||||||
|
} else {
|
||||||
|
deleteFiles(selectedFiles, false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function deleteFiles(files, deleteFromDrive) {
|
||||||
|
$.ajax({
|
||||||
|
url: ajaxurl,
|
||||||
|
type: "POST",
|
||||||
|
data: {
|
||||||
|
action: "audio_diary_delete_selected_audios",
|
||||||
|
files: files,
|
||||||
|
delete_from_drive: deleteFromDrive,
|
||||||
|
},
|
||||||
|
success: function (response) {
|
||||||
|
if (response.success) {
|
||||||
|
showToast(
|
||||||
|
"Deleted " +
|
||||||
|
(response.deleted_local || 0) +
|
||||||
|
" local file(s) and " +
|
||||||
|
(response.deleted_drive || 0) +
|
||||||
|
" Google Drive file(s) successfully!",
|
||||||
|
"success"
|
||||||
|
);
|
||||||
|
files.forEach(function (fileName) {
|
||||||
|
const $row = $('tr[data-file="' + fileName + '"]');
|
||||||
|
$row
|
||||||
|
.find(".upload-to-drive")
|
||||||
|
.text("Upload to Drive")
|
||||||
|
.removeClass("uploaded")
|
||||||
|
.prop("disabled", false);
|
||||||
|
$row.fadeOut(400, function () {
|
||||||
$(this).remove();
|
$(this).remove();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
if (response.data && response.data.drive_errors) {
|
||||||
|
showToast(response.data.drive_errors, "warning");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$.toast({
|
showToast(
|
||||||
text: "Failed to delete selected audio files: " + response.data,
|
"Failed to delete files: " + (response.data || "Unknown error"),
|
||||||
heading: 'Error',
|
"error"
|
||||||
icon: 'error',
|
);
|
||||||
showHideTransition: 'fade',
|
|
||||||
allowToastClose: true,
|
|
||||||
hideAfter: 3000,
|
|
||||||
stack: 3,
|
|
||||||
position: 'bottom-center',
|
|
||||||
textAlign: 'left',
|
|
||||||
loader: true,
|
|
||||||
loaderBg: '#FF0000',
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
error: function(jqXHR, textStatus, errorThrown) {
|
error: function (jqXHR, textStatus, errorThrown) {
|
||||||
console.log('AJAX Error: ' + textStatus + ': ' + errorThrown);
|
showToast("AJAX Error: " + textStatus + " - " + errorThrown, "error");
|
||||||
$.toast({
|
},
|
||||||
text: "AJAX Error: " + textStatus + ": " + errorThrown,
|
|
||||||
heading: 'Error',
|
|
||||||
icon: 'error',
|
|
||||||
showHideTransition: 'fade',
|
|
||||||
allowToastClose: true,
|
|
||||||
hideAfter: 3000,
|
|
||||||
stack: 3,
|
|
||||||
position: 'bottom-center',
|
|
||||||
textAlign: 'left',
|
|
||||||
loader: true,
|
|
||||||
loaderBg: '#FF0000',
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
$(".upload-to-drive").on("click", function () {
|
||||||
|
const $button = $(this);
|
||||||
|
const fileName = $button.data("name");
|
||||||
|
|
||||||
|
if ($button.hasClass("uploaded")) {
|
||||||
|
showToast("This file is already uploaded to Google Drive.", "error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$button.text("Uploading...").prop("disabled", true);
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: ajaxurl,
|
||||||
|
type: "POST",
|
||||||
|
data: {
|
||||||
|
action: "upload_to_google_drive",
|
||||||
|
file: fileName,
|
||||||
|
},
|
||||||
|
success: function (response) {
|
||||||
|
if (response.success) {
|
||||||
|
showToast("File uploaded to Google Drive successfully!", "success");
|
||||||
|
$button.text("Uploaded").addClass("uploaded").prop("disabled", true);
|
||||||
} else {
|
} else {
|
||||||
$.toast({
|
if (response.data === "File already exists in Google Drive.") {
|
||||||
text: "Please select at least one audio file to delete.",
|
showToast("This file already exists in Google Drive.", "error");
|
||||||
heading: 'Error',
|
$button
|
||||||
icon: 'error',
|
.text("Uploaded")
|
||||||
showHideTransition: 'fade',
|
.addClass("uploaded")
|
||||||
allowToastClose: true,
|
.prop("disabled", true);
|
||||||
hideAfter: 3000,
|
} else {
|
||||||
stack: 3,
|
showToast("Failed to upload: " + response.data, "error");
|
||||||
position: 'bottom-center',
|
$button.text("Upload to Drive").prop("disabled", false);
|
||||||
textAlign: 'left',
|
|
||||||
loader: true,
|
|
||||||
loaderBg: '#FF0000',
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function (jqXHR, textStatus, errorThrown) {
|
||||||
|
showToast("Upload Error: " + textStatus, "error");
|
||||||
|
$button.text("Upload to Drive").prop("disabled", false);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$("button#audioduration").on("click", function () {
|
||||||
|
var $button = $(this);
|
||||||
|
if ($button.data("loaded")) return;
|
||||||
|
var audioUrl = $button.closest("td").find(".audio-duration").data("url");
|
||||||
|
|
||||||
|
if (!audioUrl) {
|
||||||
|
$button.text("خطا");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$button.text("در حال بارگذاری...");
|
||||||
|
var audio = new Audio(audioUrl);
|
||||||
|
|
||||||
|
audio.addEventListener("canplaythrough", function () {
|
||||||
|
var duration = audio.duration;
|
||||||
|
|
||||||
|
if (isNaN(duration) || duration <= 0) {
|
||||||
|
$button.text("خطا");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var minutes = Math.floor(duration / 60);
|
||||||
|
var seconds = Math.floor(duration % 60);
|
||||||
|
var formattedDuration =
|
||||||
|
minutes + ":" + (seconds < 10 ? "0" : "") + seconds;
|
||||||
|
|
||||||
|
$button.text(formattedDuration);
|
||||||
|
$button.data("loaded", true);
|
||||||
|
});
|
||||||
|
|
||||||
|
audio.addEventListener("error", function () {
|
||||||
|
$button.text("خطا");
|
||||||
|
});
|
||||||
|
|
||||||
|
audio.load();
|
||||||
|
});
|
||||||
|
|
||||||
|
$("button.audioduration").on("click", function () {
|
||||||
|
var $button = $(this);
|
||||||
|
if ($button.data("loaded")) return;
|
||||||
|
|
||||||
|
var audioUrl = $button.closest("td").find(".audio-duration").data("url");
|
||||||
|
if (!audioUrl) {
|
||||||
|
$button.text("خطا");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$button.text("در حال بارگذاری...");
|
||||||
|
var audio = new Audio(audioUrl);
|
||||||
|
|
||||||
|
audio.addEventListener("canplaythrough", function () {
|
||||||
|
var duration = audio.duration;
|
||||||
|
|
||||||
|
if (isNaN(duration) || duration <= 0) {
|
||||||
|
$button.text("خطا");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var minutes = Math.floor(duration / 60);
|
||||||
|
var seconds = Math.floor(duration % 60);
|
||||||
|
var formattedDuration =
|
||||||
|
minutes + ":" + (seconds < 10 ? "0" : "") + seconds;
|
||||||
|
|
||||||
|
$button.text(formattedDuration);
|
||||||
|
$button.data("loaded", true);
|
||||||
|
});
|
||||||
|
|
||||||
|
audio.addEventListener("error", function () {
|
||||||
|
$button.text("خطا");
|
||||||
|
});
|
||||||
|
|
||||||
|
audio.load();
|
||||||
|
});
|
||||||
|
|
||||||
|
$(".select-audio").on("change", function () {
|
||||||
|
let count = $(".select-audio:checked").length;
|
||||||
|
$("#selected-count").text(`Selected: ${count}`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
Plugin Name: Audio diary
|
Plugin Name: Audio diary
|
||||||
Description: پلاگین دفترچه خاطرات.
|
Description: پلاگین دفترچه خاطرات.
|
||||||
Author: haakel
|
Author: haakel
|
||||||
|
Version: 2.0.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ( ! defined( 'ABSPATH' ) ) {
|
if ( ! defined( 'ABSPATH' ) ) {
|
||||||
|
|
|
||||||
|
|
@ -2,27 +2,12 @@
|
||||||
|
|
||||||
class Audio_Diary_Admin_Page {
|
class Audio_Diary_Admin_Page {
|
||||||
|
|
||||||
/**
|
|
||||||
* Instance
|
|
||||||
*
|
|
||||||
* @access private
|
|
||||||
* @var object Class object.
|
|
||||||
* @since 1.0.0
|
|
||||||
*/
|
|
||||||
private static $instance;
|
private static $instance;
|
||||||
|
|
||||||
/**
|
|
||||||
* Initiator
|
|
||||||
*
|
|
||||||
* @return object Initialized object of class.
|
|
||||||
* @since 1.0.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
public static function get_instance() {
|
public static function get_instance() {
|
||||||
if ( ! isset( self::$instance ) ) {
|
if (!isset(self::$instance)) {
|
||||||
self::$instance = new self();
|
self::$instance = new self();
|
||||||
}
|
}
|
||||||
|
|
||||||
return self::$instance;
|
return self::$instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -31,11 +16,171 @@ class Audio_Diary_Admin_Page {
|
||||||
add_action('admin_enqueue_scripts', array($this, 'enqueue_scripts'));
|
add_action('admin_enqueue_scripts', array($this, 'enqueue_scripts'));
|
||||||
add_action('wp_ajax_save_audio', array($this, 'save_audio'));
|
add_action('wp_ajax_save_audio', array($this, 'save_audio'));
|
||||||
add_action('wp_ajax_delete_audio', array($this, 'delete_audio'));
|
add_action('wp_ajax_delete_audio', array($this, 'delete_audio'));
|
||||||
add_action('wp_ajax_delete_selected_audios', array($this, 'delete_selected_audios'));
|
add_action('wp_ajax_delete_selected_audios', array($this, 'delete_selected_audios')); // نگه داشتم برای سازگاری
|
||||||
add_action('wp_ajax_download_zip', array($this,'handle_download_zip'));
|
add_action('wp_ajax_download_zip', array($this, 'handle_download_zip'));
|
||||||
|
add_action('wp_ajax_upload_to_google_drive', array($this, 'audio_diary_upload_to_google_drive'));
|
||||||
|
add_action('wp_ajax_audio_diary_delete_selected_audios', array($this, 'audio_diary_delete_selected_audios'));
|
||||||
|
add_action('wp_ajax_audio_diary_test_connection', array($this, 'test_connection'));
|
||||||
$this->create_audio_folder();
|
$this->create_audio_folder();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function test_connection() {
|
||||||
|
check_ajax_referer('audio_diary_test_connection_nonce', 'nonce');
|
||||||
|
if (!isset($_POST['folder_id']) || empty($_POST['folder_id'])) {
|
||||||
|
wp_send_json_error(__('Invalid Folder ID.', 'audio-diary'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$folder_id = sanitize_text_field($_POST['folder_id']);
|
||||||
|
require_once plugin_dir_path(__FILE__) . '../vendor/autoload.php';
|
||||||
|
$client = new Google_Client();
|
||||||
|
$client->setAuthConfig(plugin_dir_path(__FILE__) . '../config/service-account.json');
|
||||||
|
$client->addScope(Google_Service_Drive::DRIVE_METADATA_READONLY);
|
||||||
|
$service = new Google_Service_Drive($client);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$folder = $service->files->get($folder_id, ['fields' => 'id,name']);
|
||||||
|
error_log("Test connection successful for folder ID: $folder_id, Name: " . $folder->getName());
|
||||||
|
wp_send_json_success();
|
||||||
|
} catch (Google_Service_Exception $e) {
|
||||||
|
error_log("Test connection failed for $folder_id: " . $e->getMessage());
|
||||||
|
if ($e->getCode() == 404) {
|
||||||
|
wp_send_json_error(__('Folder not found. Check the Folder ID.', 'audio-diary'));
|
||||||
|
} elseif ($e->getCode() == 403) {
|
||||||
|
wp_send_json_error(__('Permission denied. Ensure the Service Account has access to this folder.', 'audio-diary'));
|
||||||
|
} else {
|
||||||
|
wp_send_json_error(__('Failed to connect: ' . $e->getMessage(), 'audio-diary'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function audio_diary_upload_to_google_drive() {
|
||||||
|
$file_name = isset($_POST['file']) ? sanitize_file_name($_POST['file']) : '';
|
||||||
|
if (!$file_name) {
|
||||||
|
error_log('Upload Error: No file specified.');
|
||||||
|
wp_send_json_error('No file specified.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$uploads = wp_upload_dir();
|
||||||
|
$file_path = $uploads['basedir'] . '/audio-diary/' . $file_name;
|
||||||
|
|
||||||
|
if (!file_exists($file_path)) {
|
||||||
|
error_log("Upload Error: File not found on server - $file_path");
|
||||||
|
wp_send_json_error('File not found on server.');
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once plugin_dir_path(__FILE__) . '../vendor/autoload.php';
|
||||||
|
$client = new Google_Client();
|
||||||
|
$client->setAuthConfig(plugin_dir_path(__FILE__) . '../config/service-account.json');
|
||||||
|
$client->addScope(Google_Service_Drive::DRIVE); // تغییر به DRIVE برای دسترسی کامل
|
||||||
|
$service = new Google_Service_Drive($client);
|
||||||
|
|
||||||
|
$target_folder_id = get_option('audio_diary_google_drive_folder_id', '1sBE78fuxRlcWouLs0mw12zLqTbWJg9jB');
|
||||||
|
$drive_file_id = get_option('google_drive_' . $file_name);
|
||||||
|
error_log("Checking file: $file_name, Drive ID: " . ($drive_file_id ? $drive_file_id : 'None'));
|
||||||
|
|
||||||
|
if ($drive_file_id) {
|
||||||
|
try {
|
||||||
|
$file = $service->files->get($drive_file_id, ['fields' => 'id,name,parents,trashed']);
|
||||||
|
$parents = $file->getParents();
|
||||||
|
$trashed = $file->getTrashed();
|
||||||
|
error_log("File $file_name exists in Google Drive with ID: $drive_file_id, Name: " . $file->getName() . ", Parents: " . implode(',', $parents) . ", Trashed: " . ($trashed ? 'Yes' : 'No'));
|
||||||
|
|
||||||
|
if (in_array($target_folder_id, $parents) && !$trashed) {
|
||||||
|
wp_send_json_error('File already exists in the target Google Drive folder.');
|
||||||
|
} else {
|
||||||
|
error_log("File $file_name is not in target folder or is trashed, proceeding to upload.");
|
||||||
|
delete_option('google_drive_' . $file_name);
|
||||||
|
}
|
||||||
|
} catch (Google_Service_Exception $e) {
|
||||||
|
error_log("Google Drive check failed for $file_name: " . $e->getMessage() . " (Code: " . $e->getCode() . ")");
|
||||||
|
if ($e->getCode() == 404) {
|
||||||
|
delete_option('google_drive_' . $file_name);
|
||||||
|
error_log("Deleted option for $file_name as it was not found in Google Drive.");
|
||||||
|
} else {
|
||||||
|
wp_send_json_error('Error checking file in Google Drive: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
error_log("No Drive ID found for $file_name, proceeding to upload.");
|
||||||
|
}
|
||||||
|
|
||||||
|
error_log("Uploading $file_name to Google Drive...");
|
||||||
|
$file = new Google_Service_Drive_DriveFile();
|
||||||
|
$file->setName($file_name);
|
||||||
|
$file->setParents([$target_folder_id]);
|
||||||
|
|
||||||
|
$result = $service->files->create($file, [
|
||||||
|
'data' => file_get_contents($file_path),
|
||||||
|
'mimeType' => 'audio/wav',
|
||||||
|
'uploadType' => 'multipart'
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($result) {
|
||||||
|
update_option('google_drive_' . $file_name, $result->id);
|
||||||
|
error_log("Upload successful for $file_name, new ID: " . $result->id);
|
||||||
|
wp_send_json_success(['file_id' => $result->id]);
|
||||||
|
} else {
|
||||||
|
error_log("Upload failed for $file_name");
|
||||||
|
wp_send_json_error('Upload failed.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function audio_diary_delete_selected_audios() {
|
||||||
|
$files = isset($_POST['files']) ? (array)$_POST['files'] : [];
|
||||||
|
$delete_from_drive = isset($_POST['delete_from_drive']) && $_POST['delete_from_drive'] === 'true';
|
||||||
|
|
||||||
|
if (empty($files)) {
|
||||||
|
wp_send_json_error('No files selected.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$uploads = wp_upload_dir();
|
||||||
|
$deleted_local = 0;
|
||||||
|
$deleted_drive = 0;
|
||||||
|
$drive_errors = [];
|
||||||
|
|
||||||
|
if ($delete_from_drive) {
|
||||||
|
require_once plugin_dir_path(__FILE__) . '../vendor/autoload.php';
|
||||||
|
$client = new Google_Client();
|
||||||
|
$client->setAuthConfig(plugin_dir_path(__FILE__) . '../config/service-account.json');
|
||||||
|
$client->addScope(Google_Service_Drive::DRIVE);
|
||||||
|
$service = new Google_Service_Drive($client);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($files as $file) {
|
||||||
|
$file_path = $uploads['basedir'] . '/audio-diary/' . sanitize_file_name($file);
|
||||||
|
$drive_file_id = get_option('google_drive_' . $file);
|
||||||
|
|
||||||
|
if ($delete_from_drive && $drive_file_id) {
|
||||||
|
try {
|
||||||
|
$service->files->delete($drive_file_id);
|
||||||
|
delete_option('google_drive_' . $file);
|
||||||
|
$deleted_drive++;
|
||||||
|
error_log("Successfully deleted file $drive_file_id from Google Drive for $file.");
|
||||||
|
} catch (Google_Service_Exception $e) {
|
||||||
|
$drive_errors[] = "Failed to delete $file from Google Drive: " . $e->getMessage() . " (Code: " . $e->getCode() . ")";
|
||||||
|
error_log($drive_errors[count($drive_errors) - 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file_exists($file_path) && unlink($file_path)) {
|
||||||
|
$deleted_local++;
|
||||||
|
error_log("Successfully deleted local file: $file_path");
|
||||||
|
} else {
|
||||||
|
error_log("No local file to delete or failed: $file_path");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($deleted_local > 0 || $deleted_drive > 0) {
|
||||||
|
$response = ['success' => true, 'deleted_local' => $deleted_local, 'deleted_drive' => $deleted_drive];
|
||||||
|
if (!empty($drive_errors)) {
|
||||||
|
$response['data'] = ['drive_errors' => implode("; ", $drive_errors)];
|
||||||
|
}
|
||||||
|
wp_send_json($response);
|
||||||
|
} else {
|
||||||
|
wp_send_json_error('Failed to delete any files.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function delete_old_zip_files() {
|
function delete_old_zip_files() {
|
||||||
$uploads = wp_upload_dir();
|
$uploads = wp_upload_dir();
|
||||||
$files = glob($uploads['basedir'] . '/audio-diary-selected-*.zip');
|
$files = glob($uploads['basedir'] . '/audio-diary-selected-*.zip');
|
||||||
|
|
@ -49,41 +194,31 @@ class Audio_Diary_Admin_Page {
|
||||||
}
|
}
|
||||||
|
|
||||||
function handle_download_zip() {
|
function handle_download_zip() {
|
||||||
if (!current_user_can('manage_options')) {
|
$files = isset($_POST['files']) ? (array)$_POST['files'] : [];
|
||||||
wp_send_json_error(['message' => 'Unauthorized']);
|
if (empty($files)) {
|
||||||
return;
|
wp_send_json_error('No files selected.');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isset($_POST['files']) || !is_array($_POST['files'])) {
|
|
||||||
wp_send_json_error(['message' => 'Invalid request']);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$selected_files = $_POST['files'];
|
|
||||||
$uploads = wp_upload_dir();
|
$uploads = wp_upload_dir();
|
||||||
|
$zip_name = 'audio-diary-' . time() . '.zip';
|
||||||
|
$zip_path = $uploads['basedir'] . '/' . $zip_name;
|
||||||
$zip = new ZipArchive();
|
$zip = new ZipArchive();
|
||||||
$zip_filename = 'audio-diary-selected-' . time() . '.zip';
|
|
||||||
$zip_filepath = $uploads['basedir'] . '/' . $zip_filename;
|
|
||||||
|
|
||||||
if ($zip->open($zip_filepath, ZipArchive::CREATE) !== TRUE) {
|
if ($zip->open($zip_path, ZipArchive::CREATE) === TRUE) {
|
||||||
wp_send_json_error(['message' => 'Cannot create zip file']);
|
foreach ($files as $file) {
|
||||||
return;
|
$file_path = $uploads['basedir'] . '/audio-diary/' . sanitize_file_name($file);
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($selected_files as $file) {
|
|
||||||
$file_path = $uploads['basedir'] . '/audio-diary/' . $file;
|
|
||||||
if (file_exists($file_path)) {
|
if (file_exists($file_path)) {
|
||||||
$zip->addFile($file_path, $file);
|
$zip->addFile($file_path, $file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$zip->close();
|
$zip->close();
|
||||||
|
|
||||||
$zip_url = $uploads['baseurl'] . '/' . $zip_filename;
|
$zip_url = $uploads['baseurl'] . '/' . $zip_name;
|
||||||
|
|
||||||
wp_send_json_success(['zip_url' => $zip_url]);
|
wp_send_json_success(['zip_url' => $zip_url]);
|
||||||
|
} else {
|
||||||
|
wp_send_json_error('Failed to create ZIP file.');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function delete_audio() {
|
function delete_audio() {
|
||||||
if (!current_user_can('manage_options')) {
|
if (!current_user_can('manage_options')) {
|
||||||
|
|
@ -109,67 +244,36 @@ class Audio_Diary_Admin_Page {
|
||||||
}
|
}
|
||||||
|
|
||||||
function delete_selected_audios() {
|
function delete_selected_audios() {
|
||||||
if (!current_user_can('manage_options')) {
|
$files = isset($_POST['files']) ? (array)$_POST['files'] : [];
|
||||||
wp_send_json_error('Unauthorized');
|
if (empty($files)) {
|
||||||
return;
|
wp_send_json_error('No files selected.');
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($_POST['files']) || !is_array($_POST['files'])) {
|
|
||||||
wp_send_json_error('No files specified');
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$uploads = wp_upload_dir();
|
$uploads = wp_upload_dir();
|
||||||
$base_path = wp_normalize_path($uploads['basedir'] . '/audio-diary/');
|
$deleted = 0;
|
||||||
$errors = [];
|
|
||||||
|
|
||||||
// Print existing files in the directory
|
foreach ($files as $file) {
|
||||||
$existing_files = glob($base_path . '*');
|
$file_path = $uploads['basedir'] . '/audio-diary/' . sanitize_file_name($file);
|
||||||
error_log("Existing files in audio-diary directory:");
|
if (file_exists($file_path) && unlink($file_path)) {
|
||||||
foreach ($existing_files as $file) {
|
$deleted++;
|
||||||
error_log(basename($file));
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($_POST['files'] as $file_name) {
|
if ($deleted > 0) {
|
||||||
$file_name = sanitize_file_name($file_name);
|
wp_send_json_success('Deleted ' . $deleted . ' files.');
|
||||||
|
|
||||||
// اصلاح نام فایل، جایگزین کردن فاصله با خط تیره
|
|
||||||
$file_name = str_replace(' ', '-', $file_name);
|
|
||||||
|
|
||||||
$file_path = wp_normalize_path($base_path . $file_name);
|
|
||||||
|
|
||||||
error_log("Trying to delete: " . $file_path);
|
|
||||||
|
|
||||||
if (file_exists($file_path)) {
|
|
||||||
if (!unlink($file_path)) {
|
|
||||||
error_log("Failed to delete: " . $file_path);
|
|
||||||
$errors[] = $file_name;
|
|
||||||
} else {
|
} else {
|
||||||
error_log("Deleted: " . $file_path);
|
wp_send_json_error('Failed to delete files.');
|
||||||
}
|
|
||||||
} else {
|
|
||||||
error_log("File not found: " . $file_path);
|
|
||||||
$errors[] = $file_name;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($errors)) {
|
|
||||||
wp_send_json_success('All files deleted successfully.');
|
|
||||||
} else {
|
|
||||||
wp_send_json_error('Failed to delete files: ' . implode(', ', $errors));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public function add_menu_item() {
|
public function add_menu_item() {
|
||||||
add_menu_page(
|
add_menu_page(
|
||||||
'Audio Diary', // عنوان صفحه
|
'Audio Diary',
|
||||||
'Audio Diary', // عنوان منو
|
'Audio Diary',
|
||||||
'manage_options', // سطح دسترسی
|
'manage_options',
|
||||||
'audio-diary', // اسلاگ صفحه
|
'audio-diary',
|
||||||
array($this, 'render_page'), // تابعی که محتوای صفحه را نمایش میدهد
|
array($this, 'render_page'),
|
||||||
'dashicons-media-audio', // آیکون منو
|
'dashicons-media-audio',
|
||||||
6
|
6
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -181,22 +285,33 @@ class Audio_Diary_Admin_Page {
|
||||||
'audio-diary-list',
|
'audio-diary-list',
|
||||||
array($this, 'render_list_page')
|
array($this, 'render_list_page')
|
||||||
);
|
);
|
||||||
|
add_submenu_page(
|
||||||
|
'audio-diary',
|
||||||
|
__('setting', 'audio-diary'),
|
||||||
|
__('setting', 'audio-diary'),
|
||||||
|
'manage_options',
|
||||||
|
'setting',
|
||||||
|
array($this, 'setting_page')
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function enqueue_scripts() {
|
public function enqueue_scripts() {
|
||||||
wp_enqueue_style('audio-diary-style', plugin_dir_url(__FILE__) . '../assets/css/style.css');
|
wp_enqueue_style('audio-diary-style', plugin_dir_url(__FILE__) . '../assets/css/style.css');
|
||||||
wp_enqueue_style('audio-diary-toast-style', plugin_dir_url(__FILE__) . '../assets/css/jquery.toast.css');
|
wp_enqueue_style('audio-diary-toast-style', plugin_dir_url(__FILE__) . '../assets/css/jquery.toast.css');
|
||||||
wp_enqueue_script('audio-diary-script', plugin_dir_url(__FILE__) ."../assets/js/audio-diary.js", array('jquery'), '1.0', true);
|
wp_enqueue_script('audio-diary-script', plugin_dir_url(__FILE__) . "../assets/js/audio-diary.js", array('jquery'), '1.0', true);
|
||||||
wp_enqueue_script('audio-diary-toast-script', plugin_dir_url(__FILE__) ."../assets/js/jquery.toast.js", array('jquery'), '1.0', true);
|
wp_enqueue_script('audio-diary-toast-script', plugin_dir_url(__FILE__) . "../assets/js/jquery.toast.js", array('jquery'), '1.0', true);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function render_page() {
|
public function render_page() {
|
||||||
include_once AUDIO_DIARY_MODULES_PATH."audio-diary-admin-page.php";
|
include_once AUDIO_DIARY_MODULES_PATH . "audio-diary-admin-page.php";
|
||||||
}
|
}
|
||||||
|
|
||||||
public function render_list_page() {
|
public function render_list_page() {
|
||||||
include_once AUDIO_DIARY_MODULES_PATH."audio-diary-admin-list-page.php";
|
include_once AUDIO_DIARY_MODULES_PATH . "audio-diary-admin-list-page.php";
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setting_page() {
|
||||||
|
include_once AUDIO_DIARY_MODULES_PATH . "setting-admin-page.php";
|
||||||
}
|
}
|
||||||
|
|
||||||
private function create_audio_folder() {
|
private function create_audio_folder() {
|
||||||
|
|
@ -206,9 +321,9 @@ class Audio_Diary_Admin_Page {
|
||||||
if (!file_exists($audio_dir)) {
|
if (!file_exists($audio_dir)) {
|
||||||
wp_mkdir_p($audio_dir);
|
wp_mkdir_p($audio_dir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function save_audio() {
|
public function save_audio() {
|
||||||
if (!current_user_can('manage_options')) {
|
if (!current_user_can('manage_options')) {
|
||||||
wp_send_json_error('Unauthorized');
|
wp_send_json_error('Unauthorized');
|
||||||
return;
|
return;
|
||||||
|
|
@ -232,9 +347,7 @@ public function save_audio() {
|
||||||
} else {
|
} else {
|
||||||
wp_send_json_error('File upload failed');
|
wp_send_json_error('File upload failed');
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
Audio_Diary_Admin_Page::get_instance();
|
Audio_Diary_Admin_Page::get_instance();
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"require": {
|
||||||
|
"google/apiclient": "^2.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -14,36 +14,42 @@ usort($audio_files, function($a, $b) {
|
||||||
?>
|
?>
|
||||||
<div class="wrap audio-diary-admin-list-page">
|
<div class="wrap audio-diary-admin-list-page">
|
||||||
<h1><?php _e('Recorded Audios', 'audio-diary'); ?></h1>
|
<h1><?php _e('Recorded Audios', 'audio-diary'); ?></h1>
|
||||||
<button id="delete-selected"><?php _e('Delete Selected', 'audio-diary'); ?></button>
|
<div class="action-buttons">
|
||||||
<button id="download-zip"><?php _e('Download Selected as ZIP', 'audio-diary'); ?></button>
|
<button id="delete-selected" class="btn btn-danger"><?php _e('Delete Selected', 'audio-diary'); ?></button>
|
||||||
<button id="select-all" data-select-all="true">Select All</button>
|
<button id="download-zip"
|
||||||
<table>
|
class="btn btn-primary"><?php _e('Download Selected as ZIP', 'audio-diary'); ?></button>
|
||||||
|
<button id="select-all" class="btn btn-secondary" data-select-all="true">Select All</button>
|
||||||
|
</div>
|
||||||
|
<div id="selected-count" class="selected-count">Selected: 0</div>
|
||||||
|
<table id="audio-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th><?php _e('Select', 'audio-diary'); ?></th>
|
<th><?php _e('Select', 'audio-diary'); ?></th>
|
||||||
<th><?php _e('Date', 'audio-diary'); ?></th>
|
<th><?php _e('Date', 'audio-diary'); ?></th>
|
||||||
<th><?php _e('Time', 'audio-diary'); ?></th>
|
<th><?php _e('Time', 'audio-diary'); ?></th>
|
||||||
<th><?php _e('Audio', 'audio-diary'); ?></th>
|
<th><?php _e('Audio', 'audio-diary'); ?></th>
|
||||||
<th><?php _e('Delete', 'audio-diary'); ?></th>
|
<th><?php _e('Actions', 'audio-diary'); ?></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<?php foreach ($audio_files as $file) :
|
<?php foreach ($audio_files as $file) :
|
||||||
$file_date = jdate("Y-m-d", filemtime($file)); // تبدیل به تاریخ شمسی
|
$file_date = jdate("Y-m-d", filemtime($file));
|
||||||
$file_time = jdate("H:i:s", filemtime($file)); // زمان را به همان صورت نمایش میدهیم
|
$file_time = jdate("H:i:s", filemtime($file));
|
||||||
$file_url = $uploads['baseurl'] . '/audio-diary/' . basename($file);
|
$file_url = $uploads['baseurl'] . '/audio-diary/' . basename($file);
|
||||||
$file_name = basename($file);
|
$file_name = basename($file);
|
||||||
?>
|
?>
|
||||||
<tr>
|
<tr data-file="<?php echo $file_name; ?>">
|
||||||
<td><input type="checkbox" class="select-audio" value="<?php echo $file_name; ?>"></td>
|
<td><input type="checkbox" class="select-audio" value="<?php echo $file_name; ?>"></td>
|
||||||
<td><?php echo $file_date; ?></td>
|
<td><?php echo $file_date; ?></td>
|
||||||
<td><?php echo $file_time; ?></td>
|
<td><?php echo $file_time; ?></td>
|
||||||
<td>
|
<td>
|
||||||
<audio controls src="<?php echo $file_url; ?>"></audio>
|
<audio controls src="<?php echo $file_url; ?>"></audio>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td class="action-cell">
|
||||||
<button class="delete-audio"
|
<button class="btn btn-small btn-download download-single" data-url="<?php echo $file_url; ?>"
|
||||||
data-file="<?php echo $file_name; ?>"><?php _e('Delete', 'audio-diary'); ?></button>
|
data-name="<?php echo $file_name; ?>">Download</button>
|
||||||
|
<button class="btn btn-small btn-upload upload-to-drive"
|
||||||
|
data-name="<?php echo $file_name; ?>">Upload to Drive</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,224 @@
|
||||||
|
<?php
|
||||||
|
if (!defined('ABSPATH')) {
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
class AudioDiarySettings {
|
||||||
|
private $folder_id_option = 'audio_diary_google_drive_folder_id';
|
||||||
|
private $default_folder_id = '1sBE78fuxRlcWouLs0mw12zLqTbWJg9jB';
|
||||||
|
|
||||||
|
public function render() {
|
||||||
|
if (isset($_POST['audio_diary_settings_submit']) && check_admin_referer('audio_diary_settings_nonce')) {
|
||||||
|
$new_folder_id = sanitize_text_field($_POST['google_drive_folder_id']);
|
||||||
|
update_option($this->folder_id_option, $new_folder_id);
|
||||||
|
echo '<div class="notice notice-success is-dismissible"><p>' . __('Settings saved successfully!', 'audio-diary') . '</p></div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
$folder_id = get_option($this->folder_id_option, $this->default_folder_id);
|
||||||
|
$folder_info = $this->get_folder_info($folder_id);
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div class="wrap audio-diary-settings">
|
||||||
|
<h1><?php _e('Audio Diary Settings', 'audio-diary'); ?></h1>
|
||||||
|
<p class="description"><?php _e('Configure the settings for your Audio Diary plugin below.', 'audio-diary'); ?></p>
|
||||||
|
|
||||||
|
<h2 class="nav-tab-wrapper">
|
||||||
|
<a href="#general" class="nav-tab nav-tab-active"><?php _e('General', 'audio-diary'); ?></a>
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<form method="post" action="" class="audio-diary-settings-form">
|
||||||
|
<?php wp_nonce_field('audio_diary_settings_nonce'); ?>
|
||||||
|
|
||||||
|
<div class="settings-section">
|
||||||
|
<h2><?php _e('Google Drive Settings', 'audio-diary'); ?></h2>
|
||||||
|
<table class="form-table">
|
||||||
|
<tr>
|
||||||
|
<th scope="row">
|
||||||
|
<label
|
||||||
|
for="google_drive_folder_id"><?php _e('Google Drive Folder ID', 'audio-diary'); ?></label>
|
||||||
|
</th>
|
||||||
|
<td>
|
||||||
|
<input type="text" id="google_drive_folder_id" name="google_drive_folder_id"
|
||||||
|
value="<?php echo esc_attr($folder_id); ?>" class="regular-text"
|
||||||
|
placeholder="<?php _e('Enter Folder ID', 'audio-diary'); ?>" />
|
||||||
|
<p class="description">
|
||||||
|
<?php _e('The ID of the Google Drive folder where audio files are stored.', 'audio-diary'); ?>
|
||||||
|
</p>
|
||||||
|
<button type="button" id="test-connection"
|
||||||
|
class="button"><?php _e('Test Connection', 'audio-diary'); ?></button>
|
||||||
|
<span id="connection-status" class="connection-status"></span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php if ($folder_info): ?>
|
||||||
|
<tr>
|
||||||
|
<th scope="row"><?php _e('Folder Name', 'audio-diary'); ?></th>
|
||||||
|
<td>
|
||||||
|
<span class="folder-info"><?php echo esc_html($folder_info['name']); ?></span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row"><?php _e('Folder URL', 'audio-diary'); ?></th>
|
||||||
|
<td>
|
||||||
|
<a href="<?php echo esc_url($folder_info['url']); ?>"
|
||||||
|
target="_blank"><?php _e('Open in Google Drive', 'audio-diary'); ?></a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php else: ?>
|
||||||
|
<tr>
|
||||||
|
<th scope="row"><?php _e('Folder Status', 'audio-diary'); ?></th>
|
||||||
|
<td>
|
||||||
|
<span
|
||||||
|
class="error"><?php _e('Folder not found or inaccessible. Verify the Folder ID and ensure it\'s shared with the Service Account.', 'audio-diary'); ?></span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endif; ?>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="submit">
|
||||||
|
<input type="submit" name="audio_diary_settings_submit" class="button button-primary"
|
||||||
|
value="<?php _e('Save Changes', 'audio-diary'); ?>" />
|
||||||
|
</p>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.audio-diary-settings {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tab-wrapper {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-section {
|
||||||
|
background: #fff;
|
||||||
|
padding: 20px;
|
||||||
|
border: 1px solid #ccd0d4;
|
||||||
|
box-shadow: 0 1px 1px rgba(0, 0, 0, .04);
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-section h2 {
|
||||||
|
margin-top: 0;
|
||||||
|
font-size: 1.3em;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-table th {
|
||||||
|
width: 200px;
|
||||||
|
padding: 15px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-table td {
|
||||||
|
padding: 15px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.folder-info {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #23282d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error {
|
||||||
|
color: #d63638;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
color: #666;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
#test-connection {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.connection-status {
|
||||||
|
margin-left: 10px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.connection-status.success {
|
||||||
|
color: #46b450;
|
||||||
|
}
|
||||||
|
|
||||||
|
.connection-status.error {
|
||||||
|
color: #d63638;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
jQuery(document).ready(function($) {
|
||||||
|
$('.nav-tab').on('click', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
$('.nav-tab').removeClass('nav-tab-active');
|
||||||
|
$(this).addClass('nav-tab-active');
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#test-connection').on('click', function() {
|
||||||
|
var $button = $(this);
|
||||||
|
var folderId = $('#google_drive_folder_id').val();
|
||||||
|
var $status = $('#connection-status');
|
||||||
|
|
||||||
|
$button.prop('disabled', true);
|
||||||
|
$status.text('<?php _e("Testing...", "audio-diary"); ?>').removeClass('success error');
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: ajaxurl,
|
||||||
|
type: 'POST',
|
||||||
|
data: {
|
||||||
|
action: 'audio_diary_test_connection',
|
||||||
|
folder_id: folderId,
|
||||||
|
nonce: '<?php echo wp_create_nonce("audio_diary_test_connection_nonce"); ?>'
|
||||||
|
},
|
||||||
|
success: function(response) {
|
||||||
|
if (response.success) {
|
||||||
|
$status.text('<?php _e("Connection successful!", "audio-diary"); ?>')
|
||||||
|
.addClass('success');
|
||||||
|
} else {
|
||||||
|
$status.text(response.data ||
|
||||||
|
'<?php _e("Connection failed.", "audio-diary"); ?>').addClass(
|
||||||
|
'error');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function() {
|
||||||
|
$status.text('<?php _e("AJAX error. Please try again.", "audio-diary"); ?>')
|
||||||
|
.addClass('error');
|
||||||
|
},
|
||||||
|
complete: function() {
|
||||||
|
$button.prop('disabled', false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
private function get_folder_info($folder_id) {
|
||||||
|
try {
|
||||||
|
require_once plugin_dir_path(__FILE__) . '../vendor/autoload.php';
|
||||||
|
$client = new Google_Client();
|
||||||
|
$client->setAuthConfig(plugin_dir_path(__FILE__) . '../config/service-account.json');
|
||||||
|
$client->addScope(Google_Service_Drive::DRIVE_METADATA_READONLY); // تغییر Scope
|
||||||
|
$service = new Google_Service_Drive($client);
|
||||||
|
|
||||||
|
$folder = $service->files->get($folder_id, ['fields' => 'id,name,webViewLink']);
|
||||||
|
return [
|
||||||
|
'name' => $folder->getName(),
|
||||||
|
'url' => $folder->getWebViewLink()
|
||||||
|
];
|
||||||
|
} catch (Exception $e) {
|
||||||
|
error_log("Failed to get folder info for $folder_id: " . $e->getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$settings = new AudioDiarySettings();
|
||||||
|
$settings->render();
|
||||||
|
?>
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload.php @generated by Composer
|
||||||
|
|
||||||
|
if (PHP_VERSION_ID < 50600) {
|
||||||
|
if (!headers_sent()) {
|
||||||
|
header('HTTP/1.1 500 Internal Server Error');
|
||||||
|
}
|
||||||
|
$err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
|
||||||
|
if (!ini_get('display_errors')) {
|
||||||
|
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
|
||||||
|
fwrite(STDERR, $err);
|
||||||
|
} elseif (!headers_sent()) {
|
||||||
|
echo $err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
trigger_error(
|
||||||
|
$err,
|
||||||
|
E_USER_ERROR
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once __DIR__ . '/composer/autoload_real.php';
|
||||||
|
|
||||||
|
return ComposerAutoloaderInit3e6e79e410cd98a8d86f36f772fe3690::getLoader();
|
||||||
|
|
@ -0,0 +1,579 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Composer.
|
||||||
|
*
|
||||||
|
* (c) Nils Adermann <naderman@naderman.de>
|
||||||
|
* Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Composer\Autoload;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
|
||||||
|
*
|
||||||
|
* $loader = new \Composer\Autoload\ClassLoader();
|
||||||
|
*
|
||||||
|
* // register classes with namespaces
|
||||||
|
* $loader->add('Symfony\Component', __DIR__.'/component');
|
||||||
|
* $loader->add('Symfony', __DIR__.'/framework');
|
||||||
|
*
|
||||||
|
* // activate the autoloader
|
||||||
|
* $loader->register();
|
||||||
|
*
|
||||||
|
* // to enable searching the include path (eg. for PEAR packages)
|
||||||
|
* $loader->setUseIncludePath(true);
|
||||||
|
*
|
||||||
|
* In this example, if you try to use a class in the Symfony\Component
|
||||||
|
* namespace or one of its children (Symfony\Component\Console for instance),
|
||||||
|
* the autoloader will first look for the class under the component/
|
||||||
|
* directory, and it will then fallback to the framework/ directory if not
|
||||||
|
* found before giving up.
|
||||||
|
*
|
||||||
|
* This class is loosely based on the Symfony UniversalClassLoader.
|
||||||
|
*
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
* @see https://www.php-fig.org/psr/psr-0/
|
||||||
|
* @see https://www.php-fig.org/psr/psr-4/
|
||||||
|
*/
|
||||||
|
class ClassLoader
|
||||||
|
{
|
||||||
|
/** @var \Closure(string):void */
|
||||||
|
private static $includeFile;
|
||||||
|
|
||||||
|
/** @var string|null */
|
||||||
|
private $vendorDir;
|
||||||
|
|
||||||
|
// PSR-4
|
||||||
|
/**
|
||||||
|
* @var array<string, array<string, int>>
|
||||||
|
*/
|
||||||
|
private $prefixLengthsPsr4 = array();
|
||||||
|
/**
|
||||||
|
* @var array<string, list<string>>
|
||||||
|
*/
|
||||||
|
private $prefixDirsPsr4 = array();
|
||||||
|
/**
|
||||||
|
* @var list<string>
|
||||||
|
*/
|
||||||
|
private $fallbackDirsPsr4 = array();
|
||||||
|
|
||||||
|
// PSR-0
|
||||||
|
/**
|
||||||
|
* List of PSR-0 prefixes
|
||||||
|
*
|
||||||
|
* Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
|
||||||
|
*
|
||||||
|
* @var array<string, array<string, list<string>>>
|
||||||
|
*/
|
||||||
|
private $prefixesPsr0 = array();
|
||||||
|
/**
|
||||||
|
* @var list<string>
|
||||||
|
*/
|
||||||
|
private $fallbackDirsPsr0 = array();
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
private $useIncludePath = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array<string, string>
|
||||||
|
*/
|
||||||
|
private $classMap = array();
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
private $classMapAuthoritative = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array<string, bool>
|
||||||
|
*/
|
||||||
|
private $missingClasses = array();
|
||||||
|
|
||||||
|
/** @var string|null */
|
||||||
|
private $apcuPrefix;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array<string, self>
|
||||||
|
*/
|
||||||
|
private static $registeredLoaders = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|null $vendorDir
|
||||||
|
*/
|
||||||
|
public function __construct($vendorDir = null)
|
||||||
|
{
|
||||||
|
$this->vendorDir = $vendorDir;
|
||||||
|
self::initializeIncludeClosure();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, list<string>>
|
||||||
|
*/
|
||||||
|
public function getPrefixes()
|
||||||
|
{
|
||||||
|
if (!empty($this->prefixesPsr0)) {
|
||||||
|
return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
|
||||||
|
}
|
||||||
|
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, list<string>>
|
||||||
|
*/
|
||||||
|
public function getPrefixesPsr4()
|
||||||
|
{
|
||||||
|
return $this->prefixDirsPsr4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return list<string>
|
||||||
|
*/
|
||||||
|
public function getFallbackDirs()
|
||||||
|
{
|
||||||
|
return $this->fallbackDirsPsr0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return list<string>
|
||||||
|
*/
|
||||||
|
public function getFallbackDirsPsr4()
|
||||||
|
{
|
||||||
|
return $this->fallbackDirsPsr4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, string> Array of classname => path
|
||||||
|
*/
|
||||||
|
public function getClassMap()
|
||||||
|
{
|
||||||
|
return $this->classMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<string, string> $classMap Class to filename map
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function addClassMap(array $classMap)
|
||||||
|
{
|
||||||
|
if ($this->classMap) {
|
||||||
|
$this->classMap = array_merge($this->classMap, $classMap);
|
||||||
|
} else {
|
||||||
|
$this->classMap = $classMap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a set of PSR-0 directories for a given prefix, either
|
||||||
|
* appending or prepending to the ones previously set for this prefix.
|
||||||
|
*
|
||||||
|
* @param string $prefix The prefix
|
||||||
|
* @param list<string>|string $paths The PSR-0 root directories
|
||||||
|
* @param bool $prepend Whether to prepend the directories
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function add($prefix, $paths, $prepend = false)
|
||||||
|
{
|
||||||
|
$paths = (array) $paths;
|
||||||
|
if (!$prefix) {
|
||||||
|
if ($prepend) {
|
||||||
|
$this->fallbackDirsPsr0 = array_merge(
|
||||||
|
$paths,
|
||||||
|
$this->fallbackDirsPsr0
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$this->fallbackDirsPsr0 = array_merge(
|
||||||
|
$this->fallbackDirsPsr0,
|
||||||
|
$paths
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$first = $prefix[0];
|
||||||
|
if (!isset($this->prefixesPsr0[$first][$prefix])) {
|
||||||
|
$this->prefixesPsr0[$first][$prefix] = $paths;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ($prepend) {
|
||||||
|
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||||
|
$paths,
|
||||||
|
$this->prefixesPsr0[$first][$prefix]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||||
|
$this->prefixesPsr0[$first][$prefix],
|
||||||
|
$paths
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a set of PSR-4 directories for a given namespace, either
|
||||||
|
* appending or prepending to the ones previously set for this namespace.
|
||||||
|
*
|
||||||
|
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||||
|
* @param list<string>|string $paths The PSR-4 base directories
|
||||||
|
* @param bool $prepend Whether to prepend the directories
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function addPsr4($prefix, $paths, $prepend = false)
|
||||||
|
{
|
||||||
|
$paths = (array) $paths;
|
||||||
|
if (!$prefix) {
|
||||||
|
// Register directories for the root namespace.
|
||||||
|
if ($prepend) {
|
||||||
|
$this->fallbackDirsPsr4 = array_merge(
|
||||||
|
$paths,
|
||||||
|
$this->fallbackDirsPsr4
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$this->fallbackDirsPsr4 = array_merge(
|
||||||
|
$this->fallbackDirsPsr4,
|
||||||
|
$paths
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
|
||||||
|
// Register directories for a new namespace.
|
||||||
|
$length = strlen($prefix);
|
||||||
|
if ('\\' !== $prefix[$length - 1]) {
|
||||||
|
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||||
|
}
|
||||||
|
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||||
|
$this->prefixDirsPsr4[$prefix] = $paths;
|
||||||
|
} elseif ($prepend) {
|
||||||
|
// Prepend directories for an already registered namespace.
|
||||||
|
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||||
|
$paths,
|
||||||
|
$this->prefixDirsPsr4[$prefix]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Append directories for an already registered namespace.
|
||||||
|
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||||
|
$this->prefixDirsPsr4[$prefix],
|
||||||
|
$paths
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a set of PSR-0 directories for a given prefix,
|
||||||
|
* replacing any others previously set for this prefix.
|
||||||
|
*
|
||||||
|
* @param string $prefix The prefix
|
||||||
|
* @param list<string>|string $paths The PSR-0 base directories
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function set($prefix, $paths)
|
||||||
|
{
|
||||||
|
if (!$prefix) {
|
||||||
|
$this->fallbackDirsPsr0 = (array) $paths;
|
||||||
|
} else {
|
||||||
|
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a set of PSR-4 directories for a given namespace,
|
||||||
|
* replacing any others previously set for this namespace.
|
||||||
|
*
|
||||||
|
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||||
|
* @param list<string>|string $paths The PSR-4 base directories
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setPsr4($prefix, $paths)
|
||||||
|
{
|
||||||
|
if (!$prefix) {
|
||||||
|
$this->fallbackDirsPsr4 = (array) $paths;
|
||||||
|
} else {
|
||||||
|
$length = strlen($prefix);
|
||||||
|
if ('\\' !== $prefix[$length - 1]) {
|
||||||
|
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||||
|
}
|
||||||
|
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||||
|
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turns on searching the include path for class files.
|
||||||
|
*
|
||||||
|
* @param bool $useIncludePath
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setUseIncludePath($useIncludePath)
|
||||||
|
{
|
||||||
|
$this->useIncludePath = $useIncludePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can be used to check if the autoloader uses the include path to check
|
||||||
|
* for classes.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function getUseIncludePath()
|
||||||
|
{
|
||||||
|
return $this->useIncludePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turns off searching the prefix and fallback directories for classes
|
||||||
|
* that have not been registered with the class map.
|
||||||
|
*
|
||||||
|
* @param bool $classMapAuthoritative
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setClassMapAuthoritative($classMapAuthoritative)
|
||||||
|
{
|
||||||
|
$this->classMapAuthoritative = $classMapAuthoritative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should class lookup fail if not found in the current class map?
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isClassMapAuthoritative()
|
||||||
|
{
|
||||||
|
return $this->classMapAuthoritative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
|
||||||
|
*
|
||||||
|
* @param string|null $apcuPrefix
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setApcuPrefix($apcuPrefix)
|
||||||
|
{
|
||||||
|
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The APCu prefix in use, or null if APCu caching is not enabled.
|
||||||
|
*
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public function getApcuPrefix()
|
||||||
|
{
|
||||||
|
return $this->apcuPrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers this instance as an autoloader.
|
||||||
|
*
|
||||||
|
* @param bool $prepend Whether to prepend the autoloader or not
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function register($prepend = false)
|
||||||
|
{
|
||||||
|
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
||||||
|
|
||||||
|
if (null === $this->vendorDir) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($prepend) {
|
||||||
|
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
|
||||||
|
} else {
|
||||||
|
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||||
|
self::$registeredLoaders[$this->vendorDir] = $this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregisters this instance as an autoloader.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function unregister()
|
||||||
|
{
|
||||||
|
spl_autoload_unregister(array($this, 'loadClass'));
|
||||||
|
|
||||||
|
if (null !== $this->vendorDir) {
|
||||||
|
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the given class or interface.
|
||||||
|
*
|
||||||
|
* @param string $class The name of the class
|
||||||
|
* @return true|null True if loaded, null otherwise
|
||||||
|
*/
|
||||||
|
public function loadClass($class)
|
||||||
|
{
|
||||||
|
if ($file = $this->findFile($class)) {
|
||||||
|
$includeFile = self::$includeFile;
|
||||||
|
$includeFile($file);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the path to the file where the class is defined.
|
||||||
|
*
|
||||||
|
* @param string $class The name of the class
|
||||||
|
*
|
||||||
|
* @return string|false The path if found, false otherwise
|
||||||
|
*/
|
||||||
|
public function findFile($class)
|
||||||
|
{
|
||||||
|
// class map lookup
|
||||||
|
if (isset($this->classMap[$class])) {
|
||||||
|
return $this->classMap[$class];
|
||||||
|
}
|
||||||
|
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (null !== $this->apcuPrefix) {
|
||||||
|
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
|
||||||
|
if ($hit) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$file = $this->findFileWithExtension($class, '.php');
|
||||||
|
|
||||||
|
// Search for Hack files if we are running on HHVM
|
||||||
|
if (false === $file && defined('HHVM_VERSION')) {
|
||||||
|
$file = $this->findFileWithExtension($class, '.hh');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null !== $this->apcuPrefix) {
|
||||||
|
apcu_add($this->apcuPrefix.$class, $file);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false === $file) {
|
||||||
|
// Remember that this class does not exist.
|
||||||
|
$this->missingClasses[$class] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the currently registered loaders keyed by their corresponding vendor directories.
|
||||||
|
*
|
||||||
|
* @return array<string, self>
|
||||||
|
*/
|
||||||
|
public static function getRegisteredLoaders()
|
||||||
|
{
|
||||||
|
return self::$registeredLoaders;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $class
|
||||||
|
* @param string $ext
|
||||||
|
* @return string|false
|
||||||
|
*/
|
||||||
|
private function findFileWithExtension($class, $ext)
|
||||||
|
{
|
||||||
|
// PSR-4 lookup
|
||||||
|
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
|
||||||
|
|
||||||
|
$first = $class[0];
|
||||||
|
if (isset($this->prefixLengthsPsr4[$first])) {
|
||||||
|
$subPath = $class;
|
||||||
|
while (false !== $lastPos = strrpos($subPath, '\\')) {
|
||||||
|
$subPath = substr($subPath, 0, $lastPos);
|
||||||
|
$search = $subPath . '\\';
|
||||||
|
if (isset($this->prefixDirsPsr4[$search])) {
|
||||||
|
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
|
||||||
|
foreach ($this->prefixDirsPsr4[$search] as $dir) {
|
||||||
|
if (file_exists($file = $dir . $pathEnd)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PSR-4 fallback dirs
|
||||||
|
foreach ($this->fallbackDirsPsr4 as $dir) {
|
||||||
|
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PSR-0 lookup
|
||||||
|
if (false !== $pos = strrpos($class, '\\')) {
|
||||||
|
// namespaced class name
|
||||||
|
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
|
||||||
|
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
|
||||||
|
} else {
|
||||||
|
// PEAR-like class name
|
||||||
|
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($this->prefixesPsr0[$first])) {
|
||||||
|
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
|
||||||
|
if (0 === strpos($class, $prefix)) {
|
||||||
|
foreach ($dirs as $dir) {
|
||||||
|
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PSR-0 fallback dirs
|
||||||
|
foreach ($this->fallbackDirsPsr0 as $dir) {
|
||||||
|
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PSR-0 include paths.
|
||||||
|
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private static function initializeIncludeClosure()
|
||||||
|
{
|
||||||
|
if (self::$includeFile !== null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scope isolated include.
|
||||||
|
*
|
||||||
|
* Prevents access to $this/self from included files.
|
||||||
|
*
|
||||||
|
* @param string $file
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
self::$includeFile = \Closure::bind(static function($file) {
|
||||||
|
include $file;
|
||||||
|
}, null, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,378 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Composer.
|
||||||
|
*
|
||||||
|
* (c) Nils Adermann <naderman@naderman.de>
|
||||||
|
* Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Composer;
|
||||||
|
|
||||||
|
use Composer\Autoload\ClassLoader;
|
||||||
|
use Composer\Semver\VersionParser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is copied in every Composer installed project and available to all
|
||||||
|
*
|
||||||
|
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
|
||||||
|
*
|
||||||
|
* To require its presence, you can require `composer-runtime-api ^2.0`
|
||||||
|
*
|
||||||
|
* @final
|
||||||
|
*/
|
||||||
|
class InstalledVersions
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var mixed[]|null
|
||||||
|
* @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
|
||||||
|
*/
|
||||||
|
private static $installed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private static $installedIsLocalDir;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool|null
|
||||||
|
*/
|
||||||
|
private static $canGetVendors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array[]
|
||||||
|
* @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||||
|
*/
|
||||||
|
private static $installedByVendor = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of all package names which are present, either by being installed, replaced or provided
|
||||||
|
*
|
||||||
|
* @return string[]
|
||||||
|
* @psalm-return list<string>
|
||||||
|
*/
|
||||||
|
public static function getInstalledPackages()
|
||||||
|
{
|
||||||
|
$packages = array();
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
$packages[] = array_keys($installed['versions']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (1 === \count($packages)) {
|
||||||
|
return $packages[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of all package names with a specific type e.g. 'library'
|
||||||
|
*
|
||||||
|
* @param string $type
|
||||||
|
* @return string[]
|
||||||
|
* @psalm-return list<string>
|
||||||
|
*/
|
||||||
|
public static function getInstalledPackagesByType($type)
|
||||||
|
{
|
||||||
|
$packagesByType = array();
|
||||||
|
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
foreach ($installed['versions'] as $name => $package) {
|
||||||
|
if (isset($package['type']) && $package['type'] === $type) {
|
||||||
|
$packagesByType[] = $name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $packagesByType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the given package is installed
|
||||||
|
*
|
||||||
|
* This also returns true if the package name is provided or replaced by another package
|
||||||
|
*
|
||||||
|
* @param string $packageName
|
||||||
|
* @param bool $includeDevRequirements
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function isInstalled($packageName, $includeDevRequirements = true)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (isset($installed['versions'][$packageName])) {
|
||||||
|
return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the given package satisfies a version constraint
|
||||||
|
*
|
||||||
|
* e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
|
||||||
|
*
|
||||||
|
* Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
|
||||||
|
*
|
||||||
|
* @param VersionParser $parser Install composer/semver to have access to this class and functionality
|
||||||
|
* @param string $packageName
|
||||||
|
* @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function satisfies(VersionParser $parser, $packageName, $constraint)
|
||||||
|
{
|
||||||
|
$constraint = $parser->parseConstraints((string) $constraint);
|
||||||
|
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
|
||||||
|
|
||||||
|
return $provided->matches($constraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a version constraint representing all the range(s) which are installed for a given package
|
||||||
|
*
|
||||||
|
* It is easier to use this via isInstalled() with the $constraint argument if you need to check
|
||||||
|
* whether a given version of a package is installed, and not just whether it exists
|
||||||
|
*
|
||||||
|
* @param string $packageName
|
||||||
|
* @return string Version constraint usable with composer/semver
|
||||||
|
*/
|
||||||
|
public static function getVersionRanges($packageName)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ranges = array();
|
||||||
|
if (isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||||
|
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
|
||||||
|
}
|
||||||
|
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
|
||||||
|
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
|
||||||
|
}
|
||||||
|
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
|
||||||
|
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
|
||||||
|
}
|
||||||
|
if (array_key_exists('provided', $installed['versions'][$packageName])) {
|
||||||
|
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return implode(' || ', $ranges);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $packageName
|
||||||
|
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
||||||
|
*/
|
||||||
|
public static function getVersion($packageName)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($installed['versions'][$packageName]['version'])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $installed['versions'][$packageName]['version'];
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $packageName
|
||||||
|
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
||||||
|
*/
|
||||||
|
public static function getPrettyVersion($packageName)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $installed['versions'][$packageName]['pretty_version'];
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $packageName
|
||||||
|
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
|
||||||
|
*/
|
||||||
|
public static function getReference($packageName)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($installed['versions'][$packageName]['reference'])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $installed['versions'][$packageName]['reference'];
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $packageName
|
||||||
|
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
|
||||||
|
*/
|
||||||
|
public static function getInstallPath($packageName)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
* @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
|
||||||
|
*/
|
||||||
|
public static function getRootPackage()
|
||||||
|
{
|
||||||
|
$installed = self::getInstalled();
|
||||||
|
|
||||||
|
return $installed[0]['root'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the raw installed.php data for custom implementations
|
||||||
|
*
|
||||||
|
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
|
||||||
|
* @return array[]
|
||||||
|
* @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
|
||||||
|
*/
|
||||||
|
public static function getRawData()
|
||||||
|
{
|
||||||
|
@trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
|
||||||
|
|
||||||
|
if (null === self::$installed) {
|
||||||
|
// only require the installed.php file if this file is loaded from its dumped location,
|
||||||
|
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||||
|
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||||
|
self::$installed = include __DIR__ . '/installed.php';
|
||||||
|
} else {
|
||||||
|
self::$installed = array();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$installed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the raw data of all installed.php which are currently loaded for custom implementations
|
||||||
|
*
|
||||||
|
* @return array[]
|
||||||
|
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||||
|
*/
|
||||||
|
public static function getAllRawData()
|
||||||
|
{
|
||||||
|
return self::getInstalled();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lets you reload the static array from another file
|
||||||
|
*
|
||||||
|
* This is only useful for complex integrations in which a project needs to use
|
||||||
|
* this class but then also needs to execute another project's autoloader in process,
|
||||||
|
* and wants to ensure both projects have access to their version of installed.php.
|
||||||
|
*
|
||||||
|
* A typical case would be PHPUnit, where it would need to make sure it reads all
|
||||||
|
* the data it needs from this class, then call reload() with
|
||||||
|
* `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
|
||||||
|
* the project in which it runs can then also use this class safely, without
|
||||||
|
* interference between PHPUnit's dependencies and the project's dependencies.
|
||||||
|
*
|
||||||
|
* @param array[] $data A vendor/composer/installed.php data set
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
|
* @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
|
||||||
|
*/
|
||||||
|
public static function reload($data)
|
||||||
|
{
|
||||||
|
self::$installed = $data;
|
||||||
|
self::$installedByVendor = array();
|
||||||
|
|
||||||
|
// when using reload, we disable the duplicate protection to ensure that self::$installed data is
|
||||||
|
// always returned, but we cannot know whether it comes from the installed.php in __DIR__ or not,
|
||||||
|
// so we have to assume it does not, and that may result in duplicate data being returned when listing
|
||||||
|
// all installed packages for example
|
||||||
|
self::$installedIsLocalDir = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array[]
|
||||||
|
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||||
|
*/
|
||||||
|
private static function getInstalled()
|
||||||
|
{
|
||||||
|
if (null === self::$canGetVendors) {
|
||||||
|
self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
|
||||||
|
}
|
||||||
|
|
||||||
|
$installed = array();
|
||||||
|
$copiedLocalDir = false;
|
||||||
|
|
||||||
|
if (self::$canGetVendors) {
|
||||||
|
$selfDir = strtr(__DIR__, '\\', '/');
|
||||||
|
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
|
||||||
|
$vendorDir = strtr($vendorDir, '\\', '/');
|
||||||
|
if (isset(self::$installedByVendor[$vendorDir])) {
|
||||||
|
$installed[] = self::$installedByVendor[$vendorDir];
|
||||||
|
} elseif (is_file($vendorDir.'/composer/installed.php')) {
|
||||||
|
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
|
||||||
|
$required = require $vendorDir.'/composer/installed.php';
|
||||||
|
self::$installedByVendor[$vendorDir] = $required;
|
||||||
|
$installed[] = $required;
|
||||||
|
if (self::$installed === null && $vendorDir.'/composer' === $selfDir) {
|
||||||
|
self::$installed = $required;
|
||||||
|
self::$installedIsLocalDir = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (self::$installedIsLocalDir && $vendorDir.'/composer' === $selfDir) {
|
||||||
|
$copiedLocalDir = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null === self::$installed) {
|
||||||
|
// only require the installed.php file if this file is loaded from its dumped location,
|
||||||
|
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||||
|
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||||
|
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
|
||||||
|
$required = require __DIR__ . '/installed.php';
|
||||||
|
self::$installed = $required;
|
||||||
|
} else {
|
||||||
|
self::$installed = array();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self::$installed !== array() && !$copiedLocalDir) {
|
||||||
|
$installed[] = self::$installed;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $installed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
|
||||||
|
Copyright (c) Nils Adermann, Jordi Boggiano
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is furnished
|
||||||
|
to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_classmap.php @generated by Composer
|
||||||
|
|
||||||
|
$vendorDir = dirname(__DIR__);
|
||||||
|
$baseDir = dirname($vendorDir);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
|
||||||
|
'Google_AccessToken_Revoke' => $vendorDir . '/google/apiclient/src/aliases.php',
|
||||||
|
'Google_AccessToken_Verify' => $vendorDir . '/google/apiclient/src/aliases.php',
|
||||||
|
'Google_AuthHandler_AuthHandlerFactory' => $vendorDir . '/google/apiclient/src/aliases.php',
|
||||||
|
'Google_AuthHandler_Guzzle6AuthHandler' => $vendorDir . '/google/apiclient/src/aliases.php',
|
||||||
|
'Google_AuthHandler_Guzzle7AuthHandler' => $vendorDir . '/google/apiclient/src/aliases.php',
|
||||||
|
'Google_Client' => $vendorDir . '/google/apiclient/src/aliases.php',
|
||||||
|
'Google_Collection' => $vendorDir . '/google/apiclient/src/aliases.php',
|
||||||
|
'Google_Exception' => $vendorDir . '/google/apiclient/src/aliases.php',
|
||||||
|
'Google_Http_Batch' => $vendorDir . '/google/apiclient/src/aliases.php',
|
||||||
|
'Google_Http_MediaFileUpload' => $vendorDir . '/google/apiclient/src/aliases.php',
|
||||||
|
'Google_Http_REST' => $vendorDir . '/google/apiclient/src/aliases.php',
|
||||||
|
'Google_Model' => $vendorDir . '/google/apiclient/src/aliases.php',
|
||||||
|
'Google_Service' => $vendorDir . '/google/apiclient/src/aliases.php',
|
||||||
|
'Google_Service_Exception' => $vendorDir . '/google/apiclient/src/aliases.php',
|
||||||
|
'Google_Service_Resource' => $vendorDir . '/google/apiclient/src/aliases.php',
|
||||||
|
'Google_Task_Composer' => $vendorDir . '/google/apiclient/src/aliases.php',
|
||||||
|
'Google_Task_Exception' => $vendorDir . '/google/apiclient/src/aliases.php',
|
||||||
|
'Google_Task_Retryable' => $vendorDir . '/google/apiclient/src/aliases.php',
|
||||||
|
'Google_Task_Runner' => $vendorDir . '/google/apiclient/src/aliases.php',
|
||||||
|
'Google_Utils_UriTemplate' => $vendorDir . '/google/apiclient/src/aliases.php',
|
||||||
|
);
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_files.php @generated by Composer
|
||||||
|
|
||||||
|
$vendorDir = dirname(__DIR__);
|
||||||
|
$baseDir = dirname($vendorDir);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
|
||||||
|
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
|
||||||
|
'37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
|
||||||
|
'1f87db08236948d07391152dccb70f04' => $vendorDir . '/google/apiclient-services/autoload.php',
|
||||||
|
'decc78cc4436b1292c6c0d151b19445c' => $vendorDir . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
|
||||||
|
'a8d3953fd9959404dd22d3dfcd0a79f0' => $vendorDir . '/google/apiclient/src/aliases.php',
|
||||||
|
);
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_namespaces.php @generated by Composer
|
||||||
|
|
||||||
|
$vendorDir = dirname(__DIR__);
|
||||||
|
$baseDir = dirname($vendorDir);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
);
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_psr4.php @generated by Composer
|
||||||
|
|
||||||
|
$vendorDir = dirname(__DIR__);
|
||||||
|
$baseDir = dirname($vendorDir);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'phpseclib3\\' => array($vendorDir . '/phpseclib/phpseclib/phpseclib'),
|
||||||
|
'Psr\\Log\\' => array($vendorDir . '/psr/log/src'),
|
||||||
|
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-factory/src', $vendorDir . '/psr/http-message/src'),
|
||||||
|
'Psr\\Http\\Client\\' => array($vendorDir . '/psr/http-client/src'),
|
||||||
|
'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'),
|
||||||
|
'ParagonIE\\ConstantTime\\' => array($vendorDir . '/paragonie/constant_time_encoding/src'),
|
||||||
|
'Monolog\\' => array($vendorDir . '/monolog/monolog/src/Monolog'),
|
||||||
|
'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
|
||||||
|
'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'),
|
||||||
|
'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'),
|
||||||
|
'Google\\Service\\' => array($vendorDir . '/google/apiclient-services/src'),
|
||||||
|
'Google\\Auth\\' => array($vendorDir . '/google/auth/src'),
|
||||||
|
'Google\\' => array($vendorDir . '/google/apiclient/src'),
|
||||||
|
'Firebase\\JWT\\' => array($vendorDir . '/firebase/php-jwt/src'),
|
||||||
|
);
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_real.php @generated by Composer
|
||||||
|
|
||||||
|
class ComposerAutoloaderInit3e6e79e410cd98a8d86f36f772fe3690
|
||||||
|
{
|
||||||
|
private static $loader;
|
||||||
|
|
||||||
|
public static function loadClassLoader($class)
|
||||||
|
{
|
||||||
|
if ('Composer\Autoload\ClassLoader' === $class) {
|
||||||
|
require __DIR__ . '/ClassLoader.php';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \Composer\Autoload\ClassLoader
|
||||||
|
*/
|
||||||
|
public static function getLoader()
|
||||||
|
{
|
||||||
|
if (null !== self::$loader) {
|
||||||
|
return self::$loader;
|
||||||
|
}
|
||||||
|
|
||||||
|
require __DIR__ . '/platform_check.php';
|
||||||
|
|
||||||
|
spl_autoload_register(array('ComposerAutoloaderInit3e6e79e410cd98a8d86f36f772fe3690', 'loadClassLoader'), true, true);
|
||||||
|
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
|
||||||
|
spl_autoload_unregister(array('ComposerAutoloaderInit3e6e79e410cd98a8d86f36f772fe3690', 'loadClassLoader'));
|
||||||
|
|
||||||
|
require __DIR__ . '/autoload_static.php';
|
||||||
|
call_user_func(\Composer\Autoload\ComposerStaticInit3e6e79e410cd98a8d86f36f772fe3690::getInitializer($loader));
|
||||||
|
|
||||||
|
$loader->register(true);
|
||||||
|
|
||||||
|
$filesToLoad = \Composer\Autoload\ComposerStaticInit3e6e79e410cd98a8d86f36f772fe3690::$files;
|
||||||
|
$requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
|
||||||
|
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||||
|
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
||||||
|
|
||||||
|
require $file;
|
||||||
|
}
|
||||||
|
}, null, null);
|
||||||
|
foreach ($filesToLoad as $fileIdentifier => $file) {
|
||||||
|
$requireFile($fileIdentifier, $file);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $loader;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,143 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_static.php @generated by Composer
|
||||||
|
|
||||||
|
namespace Composer\Autoload;
|
||||||
|
|
||||||
|
class ComposerStaticInit3e6e79e410cd98a8d86f36f772fe3690
|
||||||
|
{
|
||||||
|
public static $files = array (
|
||||||
|
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
|
||||||
|
'6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
|
||||||
|
'37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
|
||||||
|
'1f87db08236948d07391152dccb70f04' => __DIR__ . '/..' . '/google/apiclient-services/autoload.php',
|
||||||
|
'decc78cc4436b1292c6c0d151b19445c' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
|
||||||
|
'a8d3953fd9959404dd22d3dfcd0a79f0' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
|
||||||
|
);
|
||||||
|
|
||||||
|
public static $prefixLengthsPsr4 = array (
|
||||||
|
'p' =>
|
||||||
|
array (
|
||||||
|
'phpseclib3\\' => 11,
|
||||||
|
),
|
||||||
|
'P' =>
|
||||||
|
array (
|
||||||
|
'Psr\\Log\\' => 8,
|
||||||
|
'Psr\\Http\\Message\\' => 17,
|
||||||
|
'Psr\\Http\\Client\\' => 16,
|
||||||
|
'Psr\\Cache\\' => 10,
|
||||||
|
'ParagonIE\\ConstantTime\\' => 23,
|
||||||
|
),
|
||||||
|
'M' =>
|
||||||
|
array (
|
||||||
|
'Monolog\\' => 8,
|
||||||
|
),
|
||||||
|
'G' =>
|
||||||
|
array (
|
||||||
|
'GuzzleHttp\\Psr7\\' => 16,
|
||||||
|
'GuzzleHttp\\Promise\\' => 19,
|
||||||
|
'GuzzleHttp\\' => 11,
|
||||||
|
'Google\\Service\\' => 15,
|
||||||
|
'Google\\Auth\\' => 12,
|
||||||
|
'Google\\' => 7,
|
||||||
|
),
|
||||||
|
'F' =>
|
||||||
|
array (
|
||||||
|
'Firebase\\JWT\\' => 13,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
public static $prefixDirsPsr4 = array (
|
||||||
|
'phpseclib3\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib',
|
||||||
|
),
|
||||||
|
'Psr\\Log\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/psr/log/src',
|
||||||
|
),
|
||||||
|
'Psr\\Http\\Message\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/psr/http-factory/src',
|
||||||
|
1 => __DIR__ . '/..' . '/psr/http-message/src',
|
||||||
|
),
|
||||||
|
'Psr\\Http\\Client\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/psr/http-client/src',
|
||||||
|
),
|
||||||
|
'Psr\\Cache\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/psr/cache/src',
|
||||||
|
),
|
||||||
|
'ParagonIE\\ConstantTime\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src',
|
||||||
|
),
|
||||||
|
'Monolog\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/monolog/monolog/src/Monolog',
|
||||||
|
),
|
||||||
|
'GuzzleHttp\\Psr7\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/guzzlehttp/psr7/src',
|
||||||
|
),
|
||||||
|
'GuzzleHttp\\Promise\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/guzzlehttp/promises/src',
|
||||||
|
),
|
||||||
|
'GuzzleHttp\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/guzzlehttp/guzzle/src',
|
||||||
|
),
|
||||||
|
'Google\\Service\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/google/apiclient-services/src',
|
||||||
|
),
|
||||||
|
'Google\\Auth\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/google/auth/src',
|
||||||
|
),
|
||||||
|
'Google\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/google/apiclient/src',
|
||||||
|
),
|
||||||
|
'Firebase\\JWT\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/firebase/php-jwt/src',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
public static $classMap = array (
|
||||||
|
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
|
||||||
|
'Google_AccessToken_Revoke' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
|
||||||
|
'Google_AccessToken_Verify' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
|
||||||
|
'Google_AuthHandler_AuthHandlerFactory' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
|
||||||
|
'Google_AuthHandler_Guzzle6AuthHandler' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
|
||||||
|
'Google_AuthHandler_Guzzle7AuthHandler' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
|
||||||
|
'Google_Client' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
|
||||||
|
'Google_Collection' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
|
||||||
|
'Google_Exception' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
|
||||||
|
'Google_Http_Batch' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
|
||||||
|
'Google_Http_MediaFileUpload' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
|
||||||
|
'Google_Http_REST' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
|
||||||
|
'Google_Model' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
|
||||||
|
'Google_Service' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
|
||||||
|
'Google_Service_Exception' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
|
||||||
|
'Google_Service_Resource' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
|
||||||
|
'Google_Task_Composer' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
|
||||||
|
'Google_Task_Exception' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
|
||||||
|
'Google_Task_Retryable' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
|
||||||
|
'Google_Task_Runner' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
|
||||||
|
'Google_Utils_UriTemplate' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
|
||||||
|
);
|
||||||
|
|
||||||
|
public static function getInitializer(ClassLoader $loader)
|
||||||
|
{
|
||||||
|
return \Closure::bind(function () use ($loader) {
|
||||||
|
$loader->prefixLengthsPsr4 = ComposerStaticInit3e6e79e410cd98a8d86f36f772fe3690::$prefixLengthsPsr4;
|
||||||
|
$loader->prefixDirsPsr4 = ComposerStaticInit3e6e79e410cd98a8d86f36f772fe3690::$prefixDirsPsr4;
|
||||||
|
$loader->classMap = ComposerStaticInit3e6e79e410cd98a8d86f36f772fe3690::$classMap;
|
||||||
|
|
||||||
|
}, null, ClassLoader::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,209 @@
|
||||||
|
<?php return array(
|
||||||
|
'root' => array(
|
||||||
|
'name' => '__root__',
|
||||||
|
'pretty_version' => 'dev-main',
|
||||||
|
'version' => 'dev-main',
|
||||||
|
'reference' => '97074b8725c52a7110cbc94b2f0a244672943834',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../../',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev' => true,
|
||||||
|
),
|
||||||
|
'versions' => array(
|
||||||
|
'__root__' => array(
|
||||||
|
'pretty_version' => 'dev-main',
|
||||||
|
'version' => 'dev-main',
|
||||||
|
'reference' => '97074b8725c52a7110cbc94b2f0a244672943834',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../../',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'firebase/php-jwt' => array(
|
||||||
|
'pretty_version' => 'v6.11.0',
|
||||||
|
'version' => '6.11.0.0',
|
||||||
|
'reference' => '8f718f4dfc9c5d5f0c994cdfd103921b43592712',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../firebase/php-jwt',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'google/apiclient' => array(
|
||||||
|
'pretty_version' => 'v2.18.2',
|
||||||
|
'version' => '2.18.2.0',
|
||||||
|
'reference' => 'd8d201ba8a189a3cd7fb34e4da569f2ed440eee7',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../google/apiclient',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'google/apiclient-services' => array(
|
||||||
|
'pretty_version' => 'v0.396.0',
|
||||||
|
'version' => '0.396.0.0',
|
||||||
|
'reference' => 'ceb2e432e4326c6775d24f62d554395a1a9ad3dd',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../google/apiclient-services',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'google/auth' => array(
|
||||||
|
'pretty_version' => 'v1.46.0',
|
||||||
|
'version' => '1.46.0.0',
|
||||||
|
'reference' => '7fafae99a41984cbfb92508174263cf7bf3049b9',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../google/auth',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'guzzlehttp/guzzle' => array(
|
||||||
|
'pretty_version' => '7.9.2',
|
||||||
|
'version' => '7.9.2.0',
|
||||||
|
'reference' => 'd281ed313b989f213357e3be1a179f02196ac99b',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../guzzlehttp/guzzle',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'guzzlehttp/promises' => array(
|
||||||
|
'pretty_version' => '2.0.4',
|
||||||
|
'version' => '2.0.4.0',
|
||||||
|
'reference' => 'f9c436286ab2892c7db7be8c8da4ef61ccf7b455',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../guzzlehttp/promises',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'guzzlehttp/psr7' => array(
|
||||||
|
'pretty_version' => '2.7.0',
|
||||||
|
'version' => '2.7.0.0',
|
||||||
|
'reference' => 'a70f5c95fb43bc83f07c9c948baa0dc1829bf201',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../guzzlehttp/psr7',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'monolog/monolog' => array(
|
||||||
|
'pretty_version' => '3.8.1',
|
||||||
|
'version' => '3.8.1.0',
|
||||||
|
'reference' => 'aef6ee73a77a66e404dd6540934a9ef1b3c855b4',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../monolog/monolog',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'paragonie/constant_time_encoding' => array(
|
||||||
|
'pretty_version' => 'v3.0.0',
|
||||||
|
'version' => '3.0.0.0',
|
||||||
|
'reference' => 'df1e7fde177501eee2037dd159cf04f5f301a512',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../paragonie/constant_time_encoding',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'paragonie/random_compat' => array(
|
||||||
|
'pretty_version' => 'v9.99.100',
|
||||||
|
'version' => '9.99.100.0',
|
||||||
|
'reference' => '996434e5492cb4c3edcb9168db6fbb1359ef965a',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../paragonie/random_compat',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'phpseclib/phpseclib' => array(
|
||||||
|
'pretty_version' => '3.0.43',
|
||||||
|
'version' => '3.0.43.0',
|
||||||
|
'reference' => '709ec107af3cb2f385b9617be72af8cf62441d02',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../phpseclib/phpseclib',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'psr/cache' => array(
|
||||||
|
'pretty_version' => '3.0.0',
|
||||||
|
'version' => '3.0.0.0',
|
||||||
|
'reference' => 'aa5030cfa5405eccfdcb1083ce040c2cb8d253bf',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../psr/cache',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'psr/http-client' => array(
|
||||||
|
'pretty_version' => '1.0.3',
|
||||||
|
'version' => '1.0.3.0',
|
||||||
|
'reference' => 'bb5906edc1c324c9a05aa0873d40117941e5fa90',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../psr/http-client',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'psr/http-client-implementation' => array(
|
||||||
|
'dev_requirement' => false,
|
||||||
|
'provided' => array(
|
||||||
|
0 => '1.0',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'psr/http-factory' => array(
|
||||||
|
'pretty_version' => '1.1.0',
|
||||||
|
'version' => '1.1.0.0',
|
||||||
|
'reference' => '2b4765fddfe3b508ac62f829e852b1501d3f6e8a',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../psr/http-factory',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'psr/http-factory-implementation' => array(
|
||||||
|
'dev_requirement' => false,
|
||||||
|
'provided' => array(
|
||||||
|
0 => '1.0',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'psr/http-message' => array(
|
||||||
|
'pretty_version' => '2.0',
|
||||||
|
'version' => '2.0.0.0',
|
||||||
|
'reference' => '402d35bcb92c70c026d1a6a9883f06b2ead23d71',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../psr/http-message',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'psr/http-message-implementation' => array(
|
||||||
|
'dev_requirement' => false,
|
||||||
|
'provided' => array(
|
||||||
|
0 => '1.0',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'psr/log' => array(
|
||||||
|
'pretty_version' => '3.0.2',
|
||||||
|
'version' => '3.0.2.0',
|
||||||
|
'reference' => 'f16e1d5863e37f8d8c2a01719f5b34baa2b714d3',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../psr/log',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'psr/log-implementation' => array(
|
||||||
|
'dev_requirement' => false,
|
||||||
|
'provided' => array(
|
||||||
|
0 => '3.0.0',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'ralouphie/getallheaders' => array(
|
||||||
|
'pretty_version' => '3.0.3',
|
||||||
|
'version' => '3.0.3.0',
|
||||||
|
'reference' => '120b605dfeb996808c31b6477290a714d356e822',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../ralouphie/getallheaders',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'symfony/deprecation-contracts' => array(
|
||||||
|
'pretty_version' => 'v3.5.1',
|
||||||
|
'version' => '3.5.1.0',
|
||||||
|
'reference' => '74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../symfony/deprecation-contracts',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// platform_check.php @generated by Composer
|
||||||
|
|
||||||
|
$issues = array();
|
||||||
|
|
||||||
|
if (!(PHP_VERSION_ID >= 80100)) {
|
||||||
|
$issues[] = 'Your Composer dependencies require a PHP version ">= 8.1.0". You are running ' . PHP_VERSION . '.';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($issues) {
|
||||||
|
if (!headers_sent()) {
|
||||||
|
header('HTTP/1.1 500 Internal Server Error');
|
||||||
|
}
|
||||||
|
if (!ini_get('display_errors')) {
|
||||||
|
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
|
||||||
|
fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
|
||||||
|
} elseif (!headers_sent()) {
|
||||||
|
echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
trigger_error(
|
||||||
|
'Composer detected issues in your platform: ' . implode(' ', $issues),
|
||||||
|
E_USER_ERROR
|
||||||
|
);
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue