Compare commits
10 Commits
afb97f51bb
...
114da8ab73
| Author | SHA1 | Date |
|---|---|---|
|
|
114da8ab73 | |
|
|
c522954b44 | |
|
|
747c6e8a44 | |
|
|
5150554a2e | |
|
|
43bb2ab021 | |
|
|
b9ed728e86 | |
|
|
42a3cfb5d2 | |
|
|
536e643f1a | |
|
|
1194ff9650 | |
|
|
095e0a05e7 |
|
|
@ -0,0 +1,3 @@
|
|||
/node_modules
|
||||
config/service-account.json
|
||||
package-lock.json
|
||||
|
|
@ -1,80 +1,270 @@
|
|||
.audio-diary-admin-page {
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.audio-diary-admin-page body {
|
||||
background-color: #000;
|
||||
color: #fff;
|
||||
font-family: Arial, sans-serif;
|
||||
background-color: #000;
|
||||
color: #fff;
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
|
||||
.audio-diary-admin-page #recording-button {
|
||||
background-color: red;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 20px;
|
||||
font-size: 20px;
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
margin-top: 20px;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background-image: url('../img/microphone.png'); /* آدرس تصویر میکروفون */
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
background-size: 50%;
|
||||
display: block;
|
||||
margin: 20px auto; /* برای قرارگیری در وسط صفحه */
|
||||
background-color: red;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 20px;
|
||||
font-size: 20px;
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
margin-top: 20px;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background-image: url("../img/microphone.png"); /* آدرس تصویر میکروفون */
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
background-size: 50%;
|
||||
display: block;
|
||||
margin: 20px auto; /* برای قرارگیری در وسط صفحه */
|
||||
}
|
||||
|
||||
.audio-diary-admin-page #visualizer {
|
||||
display: none;
|
||||
margin-top: 20px;
|
||||
display: none;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.audio-diary-admin-page audio {
|
||||
display: none;
|
||||
margin: 20px auto;
|
||||
width: 300px;
|
||||
display: none;
|
||||
margin: 20px auto;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.audio-diary-admin-page audio.show {
|
||||
display: block;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.audio-diary-admin-page canvas {
|
||||
display: block;
|
||||
margin: 20px auto;
|
||||
border: 2px solid #c5c3c3; /* مثال: خط قرمز دور canvas */
|
||||
border-radius: 10px; /* مثال: گوشههای گرد */
|
||||
width: 100%; /* عرض 100% از والد */
|
||||
max-width: 600px; /* حداکثر عرض 600px */
|
||||
height: 100px; /* ارتفاع 100px */
|
||||
background-color: rgba(255, 255, 255, 0.1); /* مثال: زمینه نیمه شفاف سفید */
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* سایه برای دادن عمق */
|
||||
display: block;
|
||||
margin: 20px auto;
|
||||
border: 2px solid #c5c3c3; /* مثال: خط قرمز دور canvas */
|
||||
border-radius: 10px; /* مثال: گوشههای گرد */
|
||||
width: 100%; /* عرض 100% از والد */
|
||||
max-width: 600px; /* حداکثر عرض 600px */
|
||||
height: 100px; /* ارتفاع 100px */
|
||||
background-color: rgba(255, 255, 255, 0.1); /* مثال: زمینه نیمه شفاف سفید */
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* سایه برای دادن عمق */
|
||||
}
|
||||
|
||||
#visualizer {
|
||||
background-color: #f9f9f9; /* پسزمینه ملایم */
|
||||
border-radius: 8px;
|
||||
border: 1px solid #ccc;
|
||||
.audio-diary-admin-list-page #visualizer {
|
||||
background-color: #f9f9f9; /* پسزمینه ملایم */
|
||||
border-radius: 8px;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
/* تنظیمات کلی صفحه مدیریت */
|
||||
.audio-diary-admin-list-page {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background-color: #f4f4f9;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
|
||||
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
|
||||
.wrap table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
.audio-diary-admin-list-page h1 {
|
||||
color: #333;
|
||||
font-size: 24px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.wrap th, .wrap td {
|
||||
border: 1px solid #ddd;
|
||||
padding: 8px;
|
||||
.audio-diary-admin-list-page button {
|
||||
background-color: #0073aa;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px 20px;
|
||||
font-size: 14px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
.wrap th {
|
||||
background-color: #f2f2f2;
|
||||
text-align: left;
|
||||
.audio-diary-admin-list-page button:hover {
|
||||
background-color: #005177;
|
||||
}
|
||||
|
||||
.audio-diary-admin-list-page table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.audio-diary-admin-list-page th,
|
||||
.audio-diary-admin-list-page td {
|
||||
border: 1px solid #ddd;
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.audio-diary-admin-list-page th {
|
||||
background-color: #0073aa;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.audio-diary-admin-list-page tr:nth-child(even) {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
.audio-diary-admin-li st-page tr:hover {
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
|
||||
.audio-diary-admin-list-page td audio {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
/* استایلهای اضافی برای ورودیهای چکباکس و دکمه حذف */
|
||||
.audio-diary-admin-list-page .select-audio {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.audio-diary-admin-list-page .delete-audio {
|
||||
background-color: #dc3545;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 5px 10px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
.audio-diary-admin-list-page .delete-audio:hover {
|
||||
background-color: #c82333;
|
||||
}
|
||||
|
||||
/* استایلهای برای فوتر و هدر جدول */
|
||||
.audio-diary-admin-list-page thead {
|
||||
border-bottom: 2px solid #0073aa;
|
||||
}
|
||||
|
||||
.audio-diary-admin-list-page tfoot {
|
||||
border-top: 2px solid #0073aa;
|
||||
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,135 +1,427 @@
|
|||
jQuery(document).ready(function($) {
|
||||
let mediaRecorder;
|
||||
let audioChunks = [];
|
||||
let isRecording = false;
|
||||
let audioContext, analyser, dataArray, bufferLength, source;
|
||||
jQuery(document).ready(function ($) {
|
||||
let mediaRecorder;
|
||||
let audioChunks = [];
|
||||
let isRecording = false;
|
||||
let audioContext, analyser, dataArray, bufferLength, source;
|
||||
let isVisualizing = false;
|
||||
|
||||
function visualize(stream) {
|
||||
audioContext = new (window.AudioContext || window.webkitAudioContext)();
|
||||
analyser = audioContext.createAnalyser();
|
||||
source = audioContext.createMediaStreamSource(stream);
|
||||
source.connect(analyser);
|
||||
analyser.fftSize = 2048;
|
||||
bufferLength = analyser.frequencyBinCount;
|
||||
dataArray = new Uint8Array(bufferLength);
|
||||
function visualize(stream) {
|
||||
audioContext = new (window.AudioContext || window.webkitAudioContext)();
|
||||
analyser = audioContext.createAnalyser();
|
||||
source = audioContext.createMediaStreamSource(stream);
|
||||
source.connect(analyser);
|
||||
analyser.fftSize = 2048;
|
||||
bufferLength = analyser.frequencyBinCount;
|
||||
dataArray = new Uint8Array(bufferLength);
|
||||
|
||||
const canvas = document.getElementById('visualizer');
|
||||
const canvasCtx = canvas.getContext('2d');
|
||||
const canvas = document.getElementById("visualizer");
|
||||
const canvasCtx = canvas.getContext("2d");
|
||||
|
||||
function draw() {
|
||||
requestAnimationFrame(draw);
|
||||
analyser.getByteTimeDomainData(dataArray);
|
||||
function draw() {
|
||||
if (!isVisualizing) return;
|
||||
requestAnimationFrame(draw);
|
||||
analyser.getByteTimeDomainData(dataArray);
|
||||
|
||||
canvasCtx.clearRect(0, 0, canvas.width, canvas.height); // حذف پسزمینه سیاه
|
||||
canvasCtx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
// تنظیمات خط وسط
|
||||
const centerY = canvas.height / 2;
|
||||
canvasCtx.beginPath();
|
||||
canvasCtx.moveTo(0, centerY);
|
||||
canvasCtx.lineTo(canvas.width, centerY);
|
||||
canvasCtx.strokeStyle = 'rgba(0, 0, 0, 0.2)'; // خط وسط نیمه شفاف
|
||||
canvasCtx.lineWidth = 1;
|
||||
canvasCtx.stroke();
|
||||
const centerY = canvas.height / 2;
|
||||
canvasCtx.beginPath();
|
||||
canvasCtx.moveTo(0, centerY);
|
||||
canvasCtx.lineTo(canvas.width, centerY);
|
||||
canvasCtx.strokeStyle = "rgba(0, 0, 0, 0.2)";
|
||||
canvasCtx.lineWidth = 1;
|
||||
canvasCtx.stroke();
|
||||
|
||||
// تنظیمات خط موج صدا
|
||||
canvasCtx.lineWidth = 2;
|
||||
canvasCtx.strokeStyle = 'rgb(0, 0, 0)'; // خط موج صدا مشکی
|
||||
canvasCtx.lineWidth = 2;
|
||||
canvasCtx.strokeStyle = "rgb(0, 0, 0)";
|
||||
|
||||
canvasCtx.beginPath();
|
||||
let sliceWidth = canvas.width * 1.0 / bufferLength;
|
||||
let x = 0;
|
||||
canvasCtx.beginPath();
|
||||
let sliceWidth = (canvas.width * 1.0) / bufferLength;
|
||||
let x = 0;
|
||||
|
||||
for (let i = 0; i < bufferLength; i++) {
|
||||
let v = dataArray[i] / 128.0;
|
||||
let y = v * canvas.height / 2;
|
||||
for (let i = 0; i < bufferLength; i++) {
|
||||
let v = dataArray[i] / 128.0;
|
||||
let y = (v * canvas.height) / 2;
|
||||
|
||||
if (i === 0) {
|
||||
canvasCtx.moveTo(x, y);
|
||||
} else {
|
||||
canvasCtx.lineTo(x, y);
|
||||
}
|
||||
|
||||
x += sliceWidth;
|
||||
}
|
||||
|
||||
canvasCtx.lineTo(canvas.width, canvas.height / 2);
|
||||
canvasCtx.stroke();
|
||||
if (i === 0) {
|
||||
canvasCtx.moveTo(x, y);
|
||||
} else {
|
||||
canvasCtx.lineTo(x, y);
|
||||
}
|
||||
|
||||
draw();
|
||||
x += sliceWidth;
|
||||
}
|
||||
|
||||
canvasCtx.lineTo(canvas.width, canvas.height / 2);
|
||||
canvasCtx.stroke();
|
||||
}
|
||||
|
||||
$('#recording-button').on('click', function() {
|
||||
if (!isRecording) {
|
||||
navigator.mediaDevices.getUserMedia({ audio: true })
|
||||
.then(stream => {
|
||||
mediaRecorder = new MediaRecorder(stream);
|
||||
mediaRecorder.start();
|
||||
visualize(stream);
|
||||
|
||||
mediaRecorder.ondataavailable = function(event) {
|
||||
audioChunks.push(event.data);
|
||||
};
|
||||
isVisualizing = true;
|
||||
draw();
|
||||
}
|
||||
|
||||
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", // Text that is to be shown in the toast
|
||||
heading: 'Note', // Optional heading to be shown on the toast
|
||||
icon: 'success', // Type of toast icon
|
||||
showHideTransition: 'fade', // fade, slide or plain
|
||||
allowToastClose: true, // Boolean value true or false
|
||||
hideAfter: 3000, // false to make it sticky or number representing the miliseconds as time after which toast needs to be hidden
|
||||
stack: 3, // false if there should be only one toast at a time or a number representing the maximum number of toasts to be shown at a time
|
||||
position: 'bottom-center', // bottom-left or bottom-right or bottom-center or top-left or top-right or top-center or mid-center or an object representing the left, right, top, bottom values
|
||||
textAlign: 'left', // Text alignment i.e. left, right or center
|
||||
loader: true, // Whether to show loader or not. True by default
|
||||
loaderBg: '#9EC600', // Background color of the toast loader
|
||||
});
|
||||
} else {
|
||||
$.toast({
|
||||
text: "Failed to save audio", // Text that is to be shown in the toast
|
||||
heading: 'Note', // Optional heading to be shown on the toast
|
||||
icon: 'error', // Type of toast icon
|
||||
showHideTransition: 'fade', // fade, slide or plain
|
||||
allowToastClose: true, // Boolean value true or false
|
||||
hideAfter: 3000, // false to make it sticky or number representing the miliseconds as time after which toast needs to be hidden
|
||||
stack: 3, // false if there should be only one toast at a time or a number representing the maximum number of toasts to be shown at a time
|
||||
position: 'top-center', // bottom-left or bottom-right or bottom-center or top-left or top-right or top-center or mid-center or an object representing the left, right, top, bottom values
|
||||
textAlign: 'left', // Text alignment i.e. left, right or center
|
||||
loader: true, // Whether to show loader or not. True by default
|
||||
loaderBg: '#9EC600', // Background color of the toast loader
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$('#visualizer').show();
|
||||
isRecording = true;
|
||||
$('#recording-button').css('background-color', 'green'); // تغییر رنگ دکمه به سبز برای نشان دادن حالت ضبط
|
||||
});
|
||||
} else {
|
||||
mediaRecorder.stop();
|
||||
$('#visualizer').hide();
|
||||
isRecording = false;
|
||||
$('#recording-button').css('background-color', 'red'); // بازگشت به رنگ قرمز
|
||||
}
|
||||
function showToast(message, type) {
|
||||
$.toast({
|
||||
text: message,
|
||||
heading: "Note",
|
||||
icon: type,
|
||||
showHideTransition: "fade",
|
||||
allowToastClose: true,
|
||||
hideAfter: 3000,
|
||||
stack: 3,
|
||||
position: "bottom-center",
|
||||
textAlign: "left",
|
||||
loader: true,
|
||||
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");
|
||||
downloadLink.href = fileUrl;
|
||||
downloadLink.download = fileName;
|
||||
document.body.appendChild(downloadLink);
|
||||
downloadLink.click();
|
||||
document.body.removeChild(downloadLink);
|
||||
});
|
||||
|
||||
$("#download-zip").on("click", function () {
|
||||
var 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");
|
||||
var 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");
|
||||
},
|
||||
});
|
||||
} else {
|
||||
showToast("Please select at least one audio file to download.", "error");
|
||||
}
|
||||
});
|
||||
|
||||
$("#recording-button").on("click", function () {
|
||||
if (!isRecording) {
|
||||
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();
|
||||
});
|
||||
});
|
||||
if (response.data && response.data.drive_errors) {
|
||||
showToast(response.data.drive_errors, "warning");
|
||||
}
|
||||
} else {
|
||||
showToast(
|
||||
"Failed to delete files: " + (response.data || "Unknown error"),
|
||||
"error"
|
||||
);
|
||||
}
|
||||
},
|
||||
error: function (jqXHR, textStatus, errorThrown) {
|
||||
showToast("AJAX Error: " + textStatus + " - " + errorThrown, "error");
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
$(".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 {
|
||||
if (response.data === "File already exists in Google Drive.") {
|
||||
showToast("This file already exists in Google Drive.", "error");
|
||||
$button
|
||||
.text("Uploaded")
|
||||
.addClass("uploaded")
|
||||
.prop("disabled", true);
|
||||
} else {
|
||||
showToast("Failed to upload: " + response.data, "error");
|
||||
$button.text("Upload to Drive").prop("disabled", false);
|
||||
}
|
||||
}
|
||||
},
|
||||
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,12 +3,43 @@
|
|||
Plugin Name: Audio diary
|
||||
Description: پلاگین دفترچه خاطرات.
|
||||
Author: haakel
|
||||
Version: 2.0.0
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
echo "what the hell are you doing here?";
|
||||
echo "what the hell are you doing here?";
|
||||
exit;
|
||||
}
|
||||
|
||||
// فعال کردن کرون جاب در هنگام فعالسازی افزونه
|
||||
register_activation_hook(__FILE__, 'audio_diary_activate');
|
||||
function audio_diary_activate() {
|
||||
if (!wp_next_scheduled('delete_old_zip_files_cron')) {
|
||||
wp_schedule_event(time(), 'hourly', 'delete_old_zip_files_cron');
|
||||
}
|
||||
}
|
||||
|
||||
// غیرفعال کردن کرون جاب در هنگام غیرفعالسازی افزونه
|
||||
register_deactivation_hook(__FILE__, 'audio_diary_deactivate');
|
||||
function audio_diary_deactivate() {
|
||||
$timestamp = wp_next_scheduled('delete_old_zip_files_cron');
|
||||
wp_unschedule_event($timestamp, 'delete_old_zip_files_cron');
|
||||
}
|
||||
|
||||
// تعریف اکشن برای حذف فایلهای زیپ قدیمی
|
||||
add_action('delete_old_zip_files_cron', 'delete_old_zip_files');
|
||||
function delete_old_zip_files() {
|
||||
$uploads = wp_upload_dir();
|
||||
$files = glob($uploads['basedir'] . '/audio-diary-selected-*.zip');
|
||||
$time_limit = 3600; // 1 ساعت به ثانیه
|
||||
|
||||
foreach ($files as $file) {
|
||||
if (filemtime($file) < (time() - $time_limit)) {
|
||||
unlink($file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Audio_diary{
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ class Audio_Diary_loader{
|
|||
*/
|
||||
public function __construct() {
|
||||
$this->load_dependencies();
|
||||
|
||||
}
|
||||
/**
|
||||
* Load the required dependencies for this plugin.
|
||||
|
|
|
|||
|
|
@ -1,72 +1,280 @@
|
|||
<?php
|
||||
<?php
|
||||
|
||||
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() {
|
||||
if ( ! isset( self::$instance ) ) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
public static function get_instance() {
|
||||
if (!isset(self::$instance)) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
public function __construct() {
|
||||
add_action('admin_menu', array($this, 'add_menu_item'));
|
||||
add_action('admin_enqueue_scripts', array($this, 'enqueue_scripts'));
|
||||
add_action('wp_ajax_save_audio', array($this, 'save_audio'));
|
||||
add_action('wp_ajax_delete_audio_files', 'delete_audio_files');
|
||||
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_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();
|
||||
}
|
||||
|
||||
function delete_audio_files() {
|
||||
check_ajax_referer('audio-diary-nonce', '_ajax_nonce');
|
||||
|
||||
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 (!isset($_POST['files']) || !is_array($_POST['files'])) {
|
||||
wp_send_json_error('Invalid request');
|
||||
if (empty($files)) {
|
||||
wp_send_json_error('No files selected.');
|
||||
}
|
||||
|
||||
$uploads = wp_upload_dir();
|
||||
$audio_dir = $uploads['basedir'] . '/audio-diary/';
|
||||
$deleted = [];
|
||||
$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]);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($_POST['files'] as $file) {
|
||||
$file_path = $audio_dir . basename($file);
|
||||
if (file_exists($file_path) && unlink($file_path)) {
|
||||
$deleted[] = $file;
|
||||
$deleted_local++;
|
||||
error_log("Successfully deleted local file: $file_path");
|
||||
} else {
|
||||
error_log("No local file to delete or failed: $file_path");
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($deleted)) {
|
||||
wp_send_json_error('No files deleted');
|
||||
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.');
|
||||
}
|
||||
|
||||
wp_send_json_success($deleted);
|
||||
}
|
||||
|
||||
function delete_old_zip_files() {
|
||||
$uploads = wp_upload_dir();
|
||||
$files = glob($uploads['basedir'] . '/audio-diary-selected-*.zip');
|
||||
$time_limit = 3600; // 1 hour in seconds
|
||||
|
||||
foreach ($files as $file) {
|
||||
if (filemtime($file) < (time() - $time_limit)) {
|
||||
unlink($file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handle_download_zip() {
|
||||
$files = isset($_POST['files']) ? (array)$_POST['files'] : [];
|
||||
if (empty($files)) {
|
||||
wp_send_json_error('No files selected.');
|
||||
}
|
||||
|
||||
$uploads = wp_upload_dir();
|
||||
$zip_name = 'audio-diary-' . time() . '.zip';
|
||||
$zip_path = $uploads['basedir'] . '/' . $zip_name;
|
||||
$zip = new ZipArchive();
|
||||
|
||||
if ($zip->open($zip_path, ZipArchive::CREATE) === TRUE) {
|
||||
foreach ($files as $file) {
|
||||
$file_path = $uploads['basedir'] . '/audio-diary/' . sanitize_file_name($file);
|
||||
if (file_exists($file_path)) {
|
||||
$zip->addFile($file_path, $file);
|
||||
}
|
||||
}
|
||||
$zip->close();
|
||||
|
||||
$zip_url = $uploads['baseurl'] . '/' . $zip_name;
|
||||
wp_send_json_success(['zip_url' => $zip_url]);
|
||||
} else {
|
||||
wp_send_json_error('Failed to create ZIP file.');
|
||||
}
|
||||
}
|
||||
|
||||
function delete_audio() {
|
||||
if (!current_user_can('manage_options')) {
|
||||
wp_send_json_error('Unauthorized');
|
||||
return;
|
||||
}
|
||||
|
||||
if (empty($_POST['file_name'])) {
|
||||
wp_send_json_error('No file specified');
|
||||
return;
|
||||
}
|
||||
|
||||
$file_name = sanitize_file_name($_POST['file_name']);
|
||||
$uploads = wp_upload_dir();
|
||||
$file_path = $uploads['basedir'] . '/audio-diary/' . $file_name;
|
||||
|
||||
if (file_exists($file_path) && unlink($file_path)) {
|
||||
wp_send_json_success('File deleted');
|
||||
} else {
|
||||
$error = file_exists($file_path) ? 'Failed to delete file' : 'File does not exist';
|
||||
wp_send_json_error($error);
|
||||
}
|
||||
}
|
||||
|
||||
function delete_selected_audios() {
|
||||
$files = isset($_POST['files']) ? (array)$_POST['files'] : [];
|
||||
if (empty($files)) {
|
||||
wp_send_json_error('No files selected.');
|
||||
}
|
||||
|
||||
$uploads = wp_upload_dir();
|
||||
$deleted = 0;
|
||||
|
||||
foreach ($files as $file) {
|
||||
$file_path = $uploads['basedir'] . '/audio-diary/' . sanitize_file_name($file);
|
||||
if (file_exists($file_path) && unlink($file_path)) {
|
||||
$deleted++;
|
||||
}
|
||||
}
|
||||
|
||||
if ($deleted > 0) {
|
||||
wp_send_json_success('Deleted ' . $deleted . ' files.');
|
||||
} else {
|
||||
wp_send_json_error('Failed to delete files.');
|
||||
}
|
||||
}
|
||||
|
||||
public function add_menu_item() {
|
||||
add_menu_page(
|
||||
'Audio Diary', // عنوان صفحه
|
||||
'Audio Diary', // عنوان منو
|
||||
'manage_options', // سطح دسترسی
|
||||
'audio-diary', // اسلاگ صفحه
|
||||
array($this, 'render_page'), // تابعی که محتوای صفحه را نمایش میدهد
|
||||
'dashicons-media-audio', // آیکون منو
|
||||
6
|
||||
'Audio Diary',
|
||||
'Audio Diary',
|
||||
'manage_options',
|
||||
'audio-diary',
|
||||
array($this, 'render_page'),
|
||||
'dashicons-media-audio',
|
||||
6
|
||||
);
|
||||
|
||||
add_submenu_page(
|
||||
|
|
@ -77,22 +285,33 @@ class Audio_Diary_Admin_Page {
|
|||
'audio-diary-list',
|
||||
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() {
|
||||
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_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-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);
|
||||
}
|
||||
|
||||
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() {
|
||||
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() {
|
||||
|
|
@ -102,31 +321,33 @@ class Audio_Diary_Admin_Page {
|
|||
if (!file_exists($audio_dir)) {
|
||||
wp_mkdir_p($audio_dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function save_audio() {
|
||||
if (!current_user_can('manage_options')) {
|
||||
wp_send_json_error('Unauthorized');
|
||||
return;
|
||||
}
|
||||
if (!current_user_can('manage_options')) {
|
||||
wp_send_json_error('Unauthorized');
|
||||
return;
|
||||
}
|
||||
|
||||
if (empty($_FILES['audio_data'])) {
|
||||
wp_send_json_error('No file uploaded');
|
||||
return;
|
||||
}
|
||||
if (empty($_FILES['audio_data'])) {
|
||||
wp_send_json_error('No file uploaded');
|
||||
return;
|
||||
}
|
||||
|
||||
$file = $_FILES['audio_data'];
|
||||
$uploads = wp_upload_dir();
|
||||
$upload_path = $uploads['basedir'] . '/audio-diary/';
|
||||
$file = $_FILES['audio_data'];
|
||||
$uploads = wp_upload_dir();
|
||||
$upload_path = $uploads['basedir'] . '/audio-diary/';
|
||||
|
||||
$file_name = 'audio-' . time() . '.wav';
|
||||
$file_path = $upload_path . $file_name;
|
||||
$date_time = date('Y-m-d-H-i-s');
|
||||
$file_name = 'memory-' . $date_time . '.wav';
|
||||
$file_path = $upload_path . $file_name;
|
||||
|
||||
if (move_uploaded_file($file['tmp_name'], $file_path)) {
|
||||
wp_send_json_success('File uploaded');
|
||||
} else {
|
||||
wp_send_json_error('File upload failed');
|
||||
if (move_uploaded_file($file['tmp_name'], $file_path)) {
|
||||
wp_send_json_success(['message' => 'File uploaded', 'file_name' => $file_name]);
|
||||
} else {
|
||||
wp_send_json_error('File upload failed');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
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
|
|
@ -1,34 +1,56 @@
|
|||
<?php
|
||||
include_once 'jdf.php'; // اضافه کردن کتابخانه jdf
|
||||
|
||||
$uploads = wp_upload_dir();
|
||||
$audio_files = glob($uploads['basedir'] . '/audio-diary/*.wav');
|
||||
|
||||
if (!is_array($audio_files)) {
|
||||
$audio_files = [];
|
||||
}
|
||||
|
||||
usort($audio_files, function($a, $b) {
|
||||
return filemtime($b) - filemtime($a);
|
||||
});
|
||||
|
||||
?>
|
||||
<div class="wrap">
|
||||
<div class="wrap audio-diary-admin-list-page">
|
||||
<h1><?php _e('Recorded Audios', 'audio-diary'); ?></h1>
|
||||
<table>
|
||||
<div class="action-buttons">
|
||||
<button id="delete-selected" class="btn btn-danger"><?php _e('Delete Selected', 'audio-diary'); ?></button>
|
||||
<button id="download-zip"
|
||||
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>
|
||||
<tr>
|
||||
<th><?php _e('Select', 'audio-diary'); ?></th>
|
||||
<th><?php _e('Date', 'audio-diary'); ?></th>
|
||||
<th><?php _e('Time', 'audio-diary'); ?></th>
|
||||
<th><?php _e('Audio', 'audio-diary'); ?></th>
|
||||
<th><?php _e('Actions', 'audio-diary'); ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($audio_files as $file) :
|
||||
$file_date = date("Y-m-d", filemtime($file));
|
||||
$file_time = date("H:i:s", filemtime($file));
|
||||
$file_date = jdate("Y-m-d", filemtime($file));
|
||||
$file_time = jdate("H:i:s", filemtime($file));
|
||||
$file_url = $uploads['baseurl'] . '/audio-diary/' . 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><?php echo $file_date; ?></td>
|
||||
<td><?php echo $file_time; ?></td>
|
||||
<td>
|
||||
<audio controls src="<?php echo $file_url; ?>"></audio>
|
||||
</td>
|
||||
<td class="action-cell">
|
||||
<button class="btn btn-small btn-download download-single" data-url="<?php echo $file_url; ?>"
|
||||
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>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,647 @@
|
|||
<?php /* In the name of Allah = بسم اللّه الرّحمن الرّحیم */
|
||||
|
||||
/**
|
||||
* @فارسی : توابع زمان و تاریخ هجری شمسی (جلالی) در پی اچ پی
|
||||
* @name: Hijri_Shamsi,Solar(Jalali) Date and Time Functions
|
||||
* @Author : Reza Gholampanahi & WebSite : http://jdf.scr.ir
|
||||
* @License: GNU/LGPL _ Open Source & Free : [all functions]
|
||||
* @Version: 2.76 =>[ 1399/11/28 = 1442/07/04 = 2021/02/16 ]
|
||||
*/
|
||||
|
||||
/* F */
|
||||
function jdate($format, $timestamp = '', $none = '', $time_zone = 'Asia/Tehran', $tr_num = 'fa') {
|
||||
|
||||
$T_sec = 0;/* <= رفع خطاي زمان سرور ، با اعداد '+' و '-' بر حسب ثانيه */
|
||||
|
||||
if ($time_zone != 'local') date_default_timezone_set(($time_zone === '') ? 'Asia/Tehran' : $time_zone);
|
||||
$ts = $T_sec + (($timestamp === '') ? time() : tr_num($timestamp));
|
||||
$date = explode('_', date('H_i_j_n_O_P_s_w_Y', $ts));
|
||||
list($j_y, $j_m, $j_d) = gregorian_to_jalali($date[8], $date[3], $date[2]);
|
||||
$doy = ($j_m < 7) ? (($j_m - 1) * 31) + $j_d - 1 : (($j_m - 7) * 30) + $j_d + 185;
|
||||
$kab = (((($j_y + 12) % 33) % 4) == 1) ? 1 : 0;
|
||||
$sl = strlen($format);
|
||||
$out = '';
|
||||
for ($i = 0; $i < $sl; $i++) {
|
||||
$sub = substr($format, $i, 1);
|
||||
if ($sub == '\\') {
|
||||
$out .= substr($format, ++$i, 1);
|
||||
continue;
|
||||
}
|
||||
switch ($sub) {
|
||||
|
||||
case 'E':
|
||||
case 'R':
|
||||
case 'x':
|
||||
case 'X':
|
||||
$out .= 'http://jdf.scr.ir';
|
||||
break;
|
||||
|
||||
case 'B':
|
||||
case 'e':
|
||||
case 'g':
|
||||
case 'G':
|
||||
case 'h':
|
||||
case 'I':
|
||||
case 'T':
|
||||
case 'u':
|
||||
case 'Z':
|
||||
$out .= date($sub, $ts);
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
$out .= ($date[0] < 12) ? 'ق.ظ' : 'ب.ظ';
|
||||
break;
|
||||
|
||||
case 'A':
|
||||
$out .= ($date[0] < 12) ? 'قبل از ظهر' : 'بعد از ظهر';
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
$out .= (int) ($j_m / 3.1) + 1;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
$out .= $j_y . '/' . $j_m . '/' . $j_d . ' ،' . $date[0] . ':' . $date[1] . ':' . $date[6] . ' ' . $date[5];
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
$out .= (int) (($j_y + 99) / 100);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
$out .= ($j_d < 10) ? '0' . $j_d : $j_d;
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
$out .= jdate_words(array('kh' => $date[7]), ' ');
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
$out .= jdate_words(array('ff' => $j_m), ' ');
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
$out .= jdate_words(array('mm' => $j_m), ' ');
|
||||
break;
|
||||
|
||||
case 'H':
|
||||
$out .= $date[0];
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
$out .= $date[1];
|
||||
break;
|
||||
|
||||
case 'j':
|
||||
$out .= $j_d;
|
||||
break;
|
||||
|
||||
case 'J':
|
||||
$out .= jdate_words(array('rr' => $j_d), ' ');
|
||||
break;
|
||||
|
||||
case 'k';
|
||||
$out .= tr_num(100 - (int) ($doy / ($kab + 365.24) * 1000) / 10, $tr_num);
|
||||
break;
|
||||
|
||||
case 'K':
|
||||
$out .= tr_num((int) ($doy / ($kab + 365.24) * 1000) / 10, $tr_num);
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
$out .= jdate_words(array('rh' => $date[7]), ' ');
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
$out .= $kab;
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
$out .= ($j_m > 9) ? $j_m : '0' . $j_m;
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
$out .= jdate_words(array('km' => $j_m), ' ');
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
$out .= $j_m;
|
||||
break;
|
||||
|
||||
case 'N':
|
||||
$out .= $date[7] + 1;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
$jdw = ($date[7] == 6) ? 0 : $date[7] + 1;
|
||||
$dny = 364 + $kab - $doy;
|
||||
$out .= ($jdw > ($doy + 3) and $doy < 3) ? $j_y - 1 : (((3 - $dny) > $jdw and $dny < 3) ? $j_y + 1 : $j_y);
|
||||
break;
|
||||
|
||||
case 'O':
|
||||
$out .= $date[4];
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
$out .= jdate_words(array('mb' => $j_m), ' ');
|
||||
break;
|
||||
|
||||
case 'P':
|
||||
$out .= $date[5];
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
$out .= jdate_words(array('sh' => $j_y), ' ');
|
||||
break;
|
||||
|
||||
case 'Q':
|
||||
$out .= $kab + 364 - $doy;
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
$key = jdate_words(array('rh' => $date[7], 'mm' => $j_m));
|
||||
$out .= $date[0] . ':' . $date[1] . ':' . $date[6] . ' ' . $date[4] . ' ' . $key['rh'] . '، ' . $j_d . ' ' . $key['mm'] . ' ' . $j_y;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
$out .= $date[6];
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
$out .= 'ام';
|
||||
break;
|
||||
|
||||
case 't':
|
||||
$out .= ($j_m != 12) ? (31 - (int) ($j_m / 6.5)) : ($kab + 29);
|
||||
break;
|
||||
|
||||
case 'U':
|
||||
$out .= $ts;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
$out .= jdate_words(array('ss' => ($j_y % 100)), ' ');
|
||||
break;
|
||||
|
||||
case 'V':
|
||||
$out .= jdate_words(array('ss' => $j_y), ' ');
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
$out .= ($date[7] == 6) ? 0 : $date[7] + 1;
|
||||
break;
|
||||
|
||||
case 'W':
|
||||
$avs = (($date[7] == 6) ? 0 : $date[7] + 1) - ($doy % 7);
|
||||
if ($avs < 0) $avs += 7;
|
||||
$num = (int) (($doy + $avs) / 7);
|
||||
if ($avs < 4) {
|
||||
$num++;
|
||||
} elseif ($num < 1) {
|
||||
$num = ($avs == 4 or $avs == ((((($j_y % 33) % 4) - 2) == ((int) (($j_y % 33) * 0.05))) ? 5 : 4)) ? 53 : 52;
|
||||
}
|
||||
$aks = $avs + $kab;
|
||||
if ($aks == 7) $aks = 0;
|
||||
$out .= (($kab + 363 - $doy) < $aks and $aks < 3) ? '01' : (($num < 10) ? '0' . $num : $num);
|
||||
break;
|
||||
|
||||
case 'y':
|
||||
$out .= substr($j_y, 2, 2);
|
||||
break;
|
||||
|
||||
case 'Y':
|
||||
$out .= $j_y;
|
||||
break;
|
||||
|
||||
case 'z':
|
||||
$out .= $doy;
|
||||
break;
|
||||
|
||||
default:
|
||||
$out .= $sub;
|
||||
}
|
||||
}
|
||||
return ($tr_num != 'en') ? tr_num($out, 'fa', '.') : $out;
|
||||
}
|
||||
|
||||
/* F */
|
||||
function jstrftime($format, $timestamp = '', $none = '', $time_zone = 'Asia/Tehran', $tr_num = 'fa') {
|
||||
|
||||
$T_sec = 0;/* <= رفع خطاي زمان سرور ، با اعداد '+' و '-' بر حسب ثانيه */
|
||||
|
||||
if ($time_zone != 'local') date_default_timezone_set(($time_zone === '') ? 'Asia/Tehran' : $time_zone);
|
||||
$ts = $T_sec + (($timestamp === '') ? time() : tr_num($timestamp));
|
||||
$date = explode('_', date('h_H_i_j_n_s_w_Y', $ts));
|
||||
list($j_y, $j_m, $j_d) = gregorian_to_jalali($date[7], $date[4], $date[3]);
|
||||
$doy = ($j_m < 7) ? (($j_m - 1) * 31) + $j_d - 1 : (($j_m - 7) * 30) + $j_d + 185;
|
||||
$kab = (((($j_y + 12) % 33) % 4) == 1) ? 1 : 0;
|
||||
$sl = strlen($format);
|
||||
$out = '';
|
||||
for ($i = 0; $i < $sl; $i++) {
|
||||
$sub = substr($format, $i, 1);
|
||||
if ($sub == '%') {
|
||||
$sub = substr($format, ++$i, 1);
|
||||
} else {
|
||||
$out .= $sub;
|
||||
continue;
|
||||
}
|
||||
switch ($sub) {
|
||||
|
||||
/* Day */
|
||||
case 'a':
|
||||
$out .= jdate_words(array('kh' => $date[6]), ' ');
|
||||
break;
|
||||
|
||||
case 'A':
|
||||
$out .= jdate_words(array('rh' => $date[6]), ' ');
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
$out .= ($j_d < 10) ? '0' . $j_d : $j_d;
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
$out .= ($j_d < 10) ? ' ' . $j_d : $j_d;
|
||||
break;
|
||||
|
||||
case 'j':
|
||||
$out .= str_pad($doy + 1, 3, 0, STR_PAD_LEFT);
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
$out .= $date[6] + 1;
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
$out .= ($date[6] == 6) ? 0 : $date[6] + 1;
|
||||
break;
|
||||
|
||||
/* Week */
|
||||
case 'U':
|
||||
$avs = (($date[6] < 5) ? $date[6] + 2 : $date[6] - 5) - ($doy % 7);
|
||||
if ($avs < 0) $avs += 7;
|
||||
$num = (int) (($doy + $avs) / 7) + 1;
|
||||
if ($avs > 3 or $avs == 1) $num--;
|
||||
$out .= ($num < 10) ? '0' . $num : $num;
|
||||
break;
|
||||
|
||||
case 'V':
|
||||
$avs = (($date[6] == 6) ? 0 : $date[6] + 1) - ($doy % 7);
|
||||
if ($avs < 0) $avs += 7;
|
||||
$num = (int) (($doy + $avs) / 7);
|
||||
if ($avs < 4) {
|
||||
$num++;
|
||||
} elseif ($num < 1) {
|
||||
$num = ($avs == 4 or $avs == ((((($j_y % 33) % 4) - 2) == ((int) (($j_y % 33) * 0.05))) ? 5 : 4)) ? 53 : 52;
|
||||
}
|
||||
$aks = $avs + $kab;
|
||||
if ($aks == 7) $aks = 0;
|
||||
$out .= (($kab + 363 - $doy) < $aks and $aks < 3) ? '01' : (($num < 10) ? '0' . $num : $num);
|
||||
break;
|
||||
|
||||
case 'W':
|
||||
$avs = (($date[6] == 6) ? 0 : $date[6] + 1) - ($doy % 7);
|
||||
if ($avs < 0) $avs += 7;
|
||||
$num = (int) (($doy + $avs) / 7) + 1;
|
||||
if ($avs > 3) $num--;
|
||||
$out .= ($num < 10) ? '0' . $num : $num;
|
||||
break;
|
||||
|
||||
/* Month */
|
||||
case 'b':
|
||||
case 'h':
|
||||
$out .= jdate_words(array('km' => $j_m), ' ');
|
||||
break;
|
||||
|
||||
case 'B':
|
||||
$out .= jdate_words(array('mm' => $j_m), ' ');
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
$out .= ($j_m > 9) ? $j_m : '0' . $j_m;
|
||||
break;
|
||||
|
||||
/* Year */
|
||||
case 'C':
|
||||
$tmp = (int) ($j_y / 100);
|
||||
$out .= ($tmp > 9) ? $tmp : '0' . $tmp;
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
$jdw = ($date[6] == 6) ? 0 : $date[6] + 1;
|
||||
$dny = 364 + $kab - $doy;
|
||||
$out .= substr(($jdw > ($doy + 3) and $doy < 3) ? $j_y - 1 : (((3 - $dny) > $jdw and $dny < 3) ? $j_y + 1 : $j_y), 2, 2);
|
||||
break;
|
||||
|
||||
case 'G':
|
||||
$jdw = ($date[6] == 6) ? 0 : $date[6] + 1;
|
||||
$dny = 364 + $kab - $doy;
|
||||
$out .= ($jdw > ($doy + 3) and $doy < 3) ? $j_y - 1 : (((3 - $dny) > $jdw and $dny < 3) ? $j_y + 1 : $j_y);
|
||||
break;
|
||||
|
||||
case 'y':
|
||||
$out .= substr($j_y, 2, 2);
|
||||
break;
|
||||
|
||||
case 'Y':
|
||||
$out .= $j_y;
|
||||
break;
|
||||
|
||||
/* Time */
|
||||
case 'H':
|
||||
$out .= $date[1];
|
||||
break;
|
||||
|
||||
case 'I':
|
||||
$out .= $date[0];
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
$out .= ($date[0] > 9) ? $date[0] : ' ' . (int) $date[0];
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
$out .= $date[2];
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
$out .= ($date[1] < 12) ? 'قبل از ظهر' : 'بعد از ظهر';
|
||||
break;
|
||||
|
||||
case 'P':
|
||||
$out .= ($date[1] < 12) ? 'ق.ظ' : 'ب.ظ';
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
$out .= $date[0] . ':' . $date[2] . ':' . $date[5] . ' ' . (($date[1] < 12) ? 'قبل از ظهر' : 'بعد از ظهر');
|
||||
break;
|
||||
|
||||
case 'R':
|
||||
$out .= $date[1] . ':' . $date[2];
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
$out .= $date[5];
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
$out .= $date[1] . ':' . $date[2] . ':' . $date[5];
|
||||
break;
|
||||
|
||||
case 'X':
|
||||
$out .= $date[0] . ':' . $date[2] . ':' . $date[5];
|
||||
break;
|
||||
|
||||
case 'z':
|
||||
$out .= date('O', $ts);
|
||||
break;
|
||||
|
||||
case 'Z':
|
||||
$out .= date('T', $ts);
|
||||
break;
|
||||
|
||||
/* Time and Date Stamps */
|
||||
case 'c':
|
||||
$key = jdate_words(array('rh' => $date[6], 'mm' => $j_m));
|
||||
$out .= $date[1] . ':' . $date[2] . ':' . $date[5] . ' ' . date('P', $ts) . ' ' . $key['rh'] . '، ' . $j_d . ' ' . $key['mm'] . ' ' . $j_y;
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
$out .= substr($j_y, 2, 2) . '/' . (($j_m > 9) ? $j_m : '0' . $j_m) . '/' . (($j_d < 10) ? '0' . $j_d : $j_d);
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
$out .= $j_y . '-' . (($j_m > 9) ? $j_m : '0' . $j_m) . '-' . (($j_d < 10) ? '0' . $j_d : $j_d);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
$out .= $ts;
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
$out .= substr($j_y, 2, 2) . '/' . (($j_m > 9) ? $j_m : '0' . $j_m) . '/' . (($j_d < 10) ? '0' . $j_d : $j_d);
|
||||
break;
|
||||
|
||||
/* Miscellaneous */
|
||||
case 'n':
|
||||
$out .= "\n";
|
||||
break;
|
||||
|
||||
case 't':
|
||||
$out .= "\t";
|
||||
break;
|
||||
|
||||
case '%':
|
||||
$out .= '%';
|
||||
break;
|
||||
|
||||
default:
|
||||
$out .= $sub;
|
||||
}
|
||||
}
|
||||
return ($tr_num != 'en') ? tr_num($out, 'fa', '.') : $out;
|
||||
}
|
||||
|
||||
/* F */
|
||||
function jmktime($h = '', $m = '', $s = '', $jm = '', $jd = '', $jy = '', $none = '', $timezone = 'Asia/Tehran') {
|
||||
if ($timezone != 'local') date_default_timezone_set($timezone);
|
||||
if ($h === '') {
|
||||
return time();
|
||||
} else {
|
||||
list($h, $m, $s, $jm, $jd, $jy) = explode('_', tr_num($h . '_' . $m . '_' . $s . '_' . $jm . '_' . $jd . '_' . $jy));
|
||||
if ($m === '') {
|
||||
return mktime($h);
|
||||
} else {
|
||||
if ($s === '') {
|
||||
return mktime($h, $m);
|
||||
} else {
|
||||
if ($jm === '') {
|
||||
return mktime($h, $m, $s);
|
||||
} else {
|
||||
$jdate = explode('_', jdate('Y_j', '', '', $timezone, 'en'));
|
||||
if ($jd === '') {
|
||||
list($gy, $gm, $gd) = jalali_to_gregorian($jdate[0], $jm, $jdate[1]);
|
||||
return mktime($h, $m, $s, $gm);
|
||||
} else {
|
||||
if ($jy === '') {
|
||||
list($gy, $gm, $gd) = jalali_to_gregorian($jdate[0], $jm, $jd);
|
||||
return mktime($h, $m, $s, $gm, $gd);
|
||||
} else {
|
||||
list($gy, $gm, $gd) = jalali_to_gregorian($jy, $jm, $jd);
|
||||
return mktime($h, $m, $s, $gm, $gd, $gy);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* F */
|
||||
function jgetdate($timestamp = '', $none = '', $timezone = 'Asia/Tehran', $tn = 'en') {
|
||||
$ts = ($timestamp === '') ? time() : tr_num($timestamp);
|
||||
$jdate = explode('_', jdate('F_G_i_j_l_n_s_w_Y_z', $ts, '', $timezone, $tn));
|
||||
return array(
|
||||
'seconds' => tr_num((int) tr_num($jdate[6]), $tn),
|
||||
'minutes' => tr_num((int) tr_num($jdate[2]), $tn),
|
||||
'hours' => $jdate[1],
|
||||
'mday' => $jdate[3],
|
||||
'wday' => $jdate[7],
|
||||
'mon' => $jdate[5],
|
||||
'year' => $jdate[8],
|
||||
'yday' => $jdate[9],
|
||||
'weekday' => $jdate[4],
|
||||
'month' => $jdate[0],
|
||||
0 => tr_num($ts, $tn)
|
||||
);
|
||||
}
|
||||
|
||||
/* F */
|
||||
function jcheckdate($jm, $jd, $jy) {
|
||||
list($jm, $jd, $jy) = explode('_', tr_num($jm . '_' . $jd . '_' . $jy));
|
||||
$l_d = ($jm == 12 and ((($jy + 12) % 33) % 4) != 1) ? 29 : (31 - (int) ($jm / 6.5));
|
||||
return ($jm > 12 or $jd > $l_d or $jm < 1 or $jd < 1 or $jy < 1) ? false : true;
|
||||
}
|
||||
|
||||
/* F */
|
||||
function tr_num($str, $mod = 'en', $mf = '٫') {
|
||||
$num_a = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.');
|
||||
$key_a = array('۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹', $mf);
|
||||
return ($mod == 'fa') ? str_replace($num_a, $key_a, $str) : str_replace($key_a, $num_a, $str);
|
||||
}
|
||||
|
||||
/* F */
|
||||
function jdate_words($array, $mod = '') {
|
||||
foreach ($array as $type => $num) {
|
||||
$num = (int) tr_num($num);
|
||||
switch ($type) {
|
||||
|
||||
case 'ss':
|
||||
$sl = strlen($num);
|
||||
$xy3 = substr($num, 2 - $sl, 1);
|
||||
$h3 = $h34 = $h4 = '';
|
||||
if ($xy3 == 1) {
|
||||
$p34 = '';
|
||||
$k34 = array('ده', 'یازده', 'دوازده', 'سیزده', 'چهارده', 'پانزده', 'شانزده', 'هفده', 'هجده', 'نوزده');
|
||||
$h34 = $k34[substr($num, 2 - $sl, 2) - 10];
|
||||
} else {
|
||||
$xy4 = substr($num, 3 - $sl, 1);
|
||||
$p34 = ($xy3 == 0 or $xy4 == 0) ? '' : ' و ';
|
||||
$k3 = array('', '', 'بیست', 'سی', 'چهل', 'پنجاه', 'شصت', 'هفتاد', 'هشتاد', 'نود');
|
||||
$h3 = $k3[$xy3];
|
||||
$k4 = array('', 'یک', 'دو', 'سه', 'چهار', 'پنج', 'شش', 'هفت', 'هشت', 'نه');
|
||||
$h4 = $k4[$xy4];
|
||||
}
|
||||
$array[$type] = (($num > 99) ? str_replace(
|
||||
array('12', '13', '14', '19', '20'),
|
||||
array('هزار و دویست', 'هزار و سیصد', 'هزار و چهارصد', 'هزار و نهصد', 'دوهزار'),
|
||||
substr($num, 0, 2)
|
||||
) . ((substr($num, 2, 2) == '00') ? '' : ' و ') : '') . $h3 . $p34 . $h34 . $h4;
|
||||
break;
|
||||
|
||||
case 'mm':
|
||||
$key = array('فروردین', 'اردیبهشت', 'خرداد', 'تیر', 'مرداد', 'شهریور', 'مهر', 'آبان', 'آذر', 'دی', 'بهمن', 'اسفند');
|
||||
$array[$type] = $key[$num - 1];
|
||||
break;
|
||||
|
||||
case 'rr':
|
||||
$key = array(
|
||||
'یک', 'دو', 'سه', 'چهار', 'پنج', 'شش', 'هفت', 'هشت', 'نه', 'ده', 'یازده', 'دوازده', 'سیزده', 'چهارده', 'پانزده', 'شانزده', 'هفده', 'هجده', 'نوزده', 'بیست', 'بیست و یک', 'بیست و دو', 'بیست و سه', 'بیست و چهار', 'بیست و پنج', 'بیست و شش', 'بیست و هفت', 'بیست و هشت', 'بیست و نه', 'سی', 'سی و یک'
|
||||
);
|
||||
$array[$type] = $key[$num - 1];
|
||||
break;
|
||||
|
||||
case 'rh':
|
||||
$key = array('یکشنبه', 'دوشنبه', 'سه شنبه', 'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه');
|
||||
$array[$type] = $key[$num];
|
||||
break;
|
||||
|
||||
case 'sh':
|
||||
$key = array('مار', 'اسب', 'گوسفند', 'میمون', 'مرغ', 'سگ', 'خوک', 'موش', 'گاو', 'پلنگ', 'خرگوش', 'نهنگ');
|
||||
$array[$type] = $key[$num % 12];
|
||||
break;
|
||||
|
||||
case 'mb':
|
||||
$key = array('حمل', 'ثور', 'جوزا', 'سرطان', 'اسد', 'سنبله', 'میزان', 'عقرب', 'قوس', 'جدی', 'دلو', 'حوت');
|
||||
$array[$type] = $key[$num - 1];
|
||||
break;
|
||||
|
||||
case 'ff':
|
||||
$key = array('بهار', 'تابستان', 'پاییز', 'زمستان');
|
||||
$array[$type] = $key[(int) ($num / 3.1)];
|
||||
break;
|
||||
|
||||
case 'km':
|
||||
$key = array('فر', 'ار', 'خر', 'تی', 'مر', 'شه', 'مه', 'آب', 'آذ', 'دی', 'به', 'اس');
|
||||
$array[$type] = $key[$num - 1];
|
||||
break;
|
||||
|
||||
case 'kh':
|
||||
$key = array('ی', 'د', 'س', 'چ', 'پ', 'ج', 'ش');
|
||||
$array[$type] = $key[$num];
|
||||
break;
|
||||
|
||||
default:
|
||||
$array[$type] = $num;
|
||||
}
|
||||
}
|
||||
return ($mod === '') ? $array : implode($mod, $array);
|
||||
}
|
||||
|
||||
|
||||
/** Gregorian & Jalali (Hijri_Shamsi,Solar) Date Converter Functions
|
||||
Author: JDF.SCR.IR =>> Download Full Version : http://jdf.scr.ir/jdf
|
||||
License: GNU/LGPL _ Open Source & Free :: Version: 2.80 : [2020=1399]
|
||||
---------------------------------------------------------------------
|
||||
355746=361590-5844 & 361590=(30*33*365)+(30*8) & 5844=(16*365)+(16/4)
|
||||
355666=355746-79-1 & 355668=355746-79+1 & 1595=605+990 & 605=621-16
|
||||
990=30*33 & 12053=(365*33)+(32/4) & 36524=(365*100)+(100/4)-(100/100)
|
||||
1461=(365*4)+(4/4) & 146097=(365*400)+(400/4)-(400/100)+(400/400) */
|
||||
|
||||
/* F */
|
||||
function gregorian_to_jalali($gy, $gm, $gd, $mod = '') {
|
||||
list($gy, $gm, $gd) = explode('_', tr_num($gy . '_' . $gm . '_' . $gd));/* <= Extra :اين سطر ، جزء تابع اصلي نيست */
|
||||
$g_d_m = array(0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334);
|
||||
$gy2 = ($gm > 2) ? ($gy + 1) : $gy;
|
||||
$days = 355666 + (365 * $gy) + ((int) (($gy2 + 3) / 4)) - ((int) (($gy2 + 99) / 100)) + ((int) (($gy2 + 399) / 400)) + $gd + $g_d_m[$gm - 1];
|
||||
$jy = -1595 + (33 * ((int) ($days / 12053)));
|
||||
$days %= 12053;
|
||||
$jy += 4 * ((int) ($days / 1461));
|
||||
$days %= 1461;
|
||||
if ($days > 365) {
|
||||
$jy += (int) (($days - 1) / 365);
|
||||
$days = ($days - 1) % 365;
|
||||
}
|
||||
if ($days < 186) {
|
||||
$jm = 1 + (int) ($days / 31);
|
||||
$jd = 1 + ($days % 31);
|
||||
} else {
|
||||
$jm = 7 + (int) (($days - 186) / 30);
|
||||
$jd = 1 + (($days - 186) % 30);
|
||||
}
|
||||
return ($mod == '') ? array($jy, $jm, $jd) : $jy . $mod . $jm . $mod . $jd;
|
||||
}
|
||||
|
||||
/* F */
|
||||
function jalali_to_gregorian($jy, $jm, $jd, $mod = '') {
|
||||
list($jy, $jm, $jd) = explode('_', tr_num($jy . '_' . $jm . '_' . $jd));/* <= Extra :اين سطر ، جزء تابع اصلي نيست */
|
||||
$jy += 1595;
|
||||
$days = -355668 + (365 * $jy) + (((int) ($jy / 33)) * 8) + ((int) ((($jy % 33) + 3) / 4)) + $jd + (($jm < 7) ? ($jm - 1) * 31 : (($jm - 7) * 30) + 186);
|
||||
$gy = 400 * ((int) ($days / 146097));
|
||||
$days %= 146097;
|
||||
if ($days > 36524) {
|
||||
$gy += 100 * ((int) (--$days / 36524));
|
||||
$days %= 36524;
|
||||
if ($days >= 365) $days++;
|
||||
}
|
||||
$gy += 4 * ((int) ($days / 1461));
|
||||
$days %= 1461;
|
||||
if ($days > 365) {
|
||||
$gy += (int) (($days - 1) / 365);
|
||||
$days = ($days - 1) % 365;
|
||||
}
|
||||
$gd = $days + 1;
|
||||
$sal_a = array(0, 31, (($gy % 4 == 0 and $gy % 100 != 0) or ($gy % 400 == 0)) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
|
||||
for ($gm = 0; $gm < 13 and $gd > $sal_a[$gm]; $gm++) $gd -= $sal_a[$gm];
|
||||
return ($mod == '') ? array($gy, $gm, $gd) : $gy . $mod . $gm . $mod . $gd;
|
||||
}
|
||||
|
|
@ -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();
|
||||
?>
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
{
|
||||
"name": "TuneTales",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"node_modules/jquery-toast-plugin": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/jquery-toast-plugin/-/jquery-toast-plugin-1.3.2.tgz",
|
||||
"integrity": "sha512-0j/nfqA2FHFuJXp8QL33EVVCY//TDVfq4LULhTbasZYl2aZlX6YiSF5IGrI31dQiS9S4JkXBUfX3rMJcfl/u/g=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,147 +0,0 @@
|
|||
# Jquery Toast Plugin
|
||||
|
||||
A plugin to show highly customizable notifications to the user.
|
||||
|
||||
<img src="http://i.imgur.com/RRrb0KE.png" />
|
||||
|
||||
# How to use
|
||||
|
||||
- You can install the plugin via Bower:
|
||||
|
||||
```js
|
||||
bower install jquery-toast-plugin
|
||||
```
|
||||
|
||||
or via `npm`
|
||||
|
||||
```js
|
||||
npm install jquery-toast-plugin
|
||||
```
|
||||
|
||||
Or directly download the repository and place the content of `dist` wherever you can access them.
|
||||
- Include the CSS and JS files.
|
||||
- Simply do ```$.toast('Toast message to be shown')``` Of course it would be the world's simplest toast message but believe me **you can do a lot more** with the options.
|
||||
|
||||
# Demo
|
||||
For some quick demos and a detailed documentation accompanied by the demos for each of the available options can be accessed through http://kamranahmed.info/toast
|
||||
|
||||
## Quick usage examples
|
||||
**Simple textual toast**
|
||||
```javascript
|
||||
// Non sticky version
|
||||
$.toast("Lorem ipsum dolor sit amet, consectetur adipisicing elit. Hic, consequuntur doloremque eveniet eius eaque dicta repudiandae illo ullam. Minima itaque sint magnam dolorum asperiores repudiandae dignissimos expedita, voluptatum vitae velit.")
|
||||
// Sticky version
|
||||
$.toast({
|
||||
text : "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Hic, consequuntur doloremque eveniet eius eaque dicta repudiandae illo ullam. Minima itaque sint magnam dolorum asperiores repudiandae dignissimos expedita, voluptatum vitae velit.",
|
||||
hideAfter : false
|
||||
})
|
||||
```
|
||||
|
||||
**Toast using HTML as a text**
|
||||
```javascript
|
||||
// Non sticky
|
||||
$.toast("Let's test some HTML stuff... <a href='#'>github</a>")
|
||||
// sticky
|
||||
$.toast({
|
||||
text : "<strong>Remember!</strong> You can <span style='font-weight: bold; color:red;' class='horribly-styled'>always</span> introduce your own × HTML and <span style='font-size: 18px;'>CSS</span> in the toast.",
|
||||
hideAfter : false
|
||||
})
|
||||
```
|
||||
|
||||
**Unordered list elements as the text of toast using array**
|
||||
```javascript
|
||||
// Non sticky version
|
||||
$.toast(["Ubuntu : One of it's kind", "Sublime Text : Productivity unleashed", "HeidiSQL : Just love it", "Github : Just Lovely"])
|
||||
// Sticky version
|
||||
$.toast({
|
||||
text : ["Ubuntu : One of it's kind", "Sublime Text : Productivity unleashed", "HeidiSQL : Just love it", "Github : Just Lovely"],
|
||||
hideAfter : false
|
||||
})
|
||||
```
|
||||
|
||||
**Changing the animations**
|
||||
```javascript
|
||||
$.toast({
|
||||
text : "Let's test some HTML stuff... <a href='#'>github</a>",
|
||||
showHideTransition : 'slide' // It can be plain, fade or slide
|
||||
})
|
||||
```
|
||||
|
||||
**Changing the formatting**
|
||||
```javascript
|
||||
$.toast({
|
||||
text : "Let's test some HTML stuff... <a href='#'>github</a>",
|
||||
showHideTransition : 'slide', // It can be plain, fade or slide
|
||||
bgColor : 'blue', // Background color for toast
|
||||
textColor : '#eee', // text color
|
||||
allowToastClose : false, // Show the close button or not
|
||||
hideAfter : 5000, // `false` to make it sticky or time in miliseconds to hide after
|
||||
stack : 5, // `fakse` to show one stack at a time count showing the number of toasts that can be shown at once
|
||||
textAlign : 'left', // Alignment of text i.e. left, right, center
|
||||
position : 'bottom-left' // bottom-left or bottom-right or bottom-center or top-left or top-right or top-center or mid-center or an object representing the left, right, top, bottom values to position the toast on page
|
||||
})
|
||||
```
|
||||
|
||||
**Resetting the toast**
|
||||
```javascript
|
||||
var myToast = $.toast('Some toast that needs to be removed.');
|
||||
myToast.reset(); // remove the toast "Some toast that needs to be removed"
|
||||
```
|
||||
What if I want to reset all the toasts at once? You may ask. Well in that case, you can do the following:
|
||||
```javascript
|
||||
$.toast().reset('all');
|
||||
```
|
||||
|
||||
**Updating the toast**
|
||||
Suppose, you had shown some toast upon the page, a sticky toast for example and now you want to update the toast. You can do the following
|
||||
|
||||
```javascript
|
||||
var myToast = $.toast({
|
||||
text : 'Some toast that needs to show the success message after the ajax call.',
|
||||
hideAfter : false,
|
||||
bgColor : '#E01A31'
|
||||
});
|
||||
|
||||
window.setTimeout(function(){
|
||||
myToast.update({
|
||||
text : '<strong>Updated after a few seconds</strong>',
|
||||
bgColor : '#23B65D'
|
||||
});
|
||||
}, 5000);
|
||||
```
|
||||
To learn more about how to use and customize it, head to <a href="http://kamranahmed.info/toast" target="_blank">http://kamranahmed.info/toast</a>. Also you can find a customizer there that will let you modify the look and feel of the toast however you like it.
|
||||
|
||||
<hr>
|
||||
|
||||
You can simply download the repo or if you are in rush the <a href="https://raw.githubusercontent.com/kamranahmedse/jquery-toast-plugin/master/jquery.toast.min.css" target="_blank">minified CSS</a> or <a href="https://raw.githubusercontent.com/kamranahmedse/jquery-toast-plugin/master/jquery.toast.css">non-minified CSS</a> can be found and <a href="https://raw.githubusercontent.com/kamranahmedse/jquery-toast-plugin/master/jquery.toast.min.js" target="_blank">minified JS</a> and <a href="https://raw.githubusercontent.com/kamranahmedse/jquery-toast-plugin/master/jquery.toast.js" target="_blank">non minified JS</a> can also be found.
|
||||
|
||||
# Features
|
||||
<ul>
|
||||
<li>Show different types of toasts i.e. informational, warning, errors and success</li>
|
||||
<li>Custom <strong>toast background color</strong> and <strong>text color</strong></li>
|
||||
<li>Ability to <strong>hack the CSS</strong> to add your own thing</li>
|
||||
<li>
|
||||
<strong>Text can be</strong> provided in the form of
|
||||
<ul>
|
||||
<li><strong>Array</strong> (It's elements will be changed to an un ordered list)</li>
|
||||
<li><strong>Simple text</strong></li>
|
||||
<li><strong>HTML</strong></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><strong>Events support</strong> i.e. <code>beforeHide</code>, <code>afterHidden</code>, <code>beforeShow</code>, <code>afterShown</code></li>
|
||||
|
||||
<li><code>Fade</code> and <code>Slide</code> show/hide transitions support (More to come)</li>
|
||||
<li>Supports showing the loader for the toast</li>
|
||||
<li>You can <strong>position the toast, wherever you want</strong> there is support for <code>top-left</code>, <code>top-right</code> <code>bottom-left</code> and <strong>bottom-right</strong>, <code>top-center</code>, <code>bottom-center</code> and <code>mid-center</code> ...sighs! That's a whole lot of options, isn't it? No, you say. Ok then here is the most exciting thing, you can also introduce <strong>your own positioning</strong> just <strong>by passing a simple js object</strong> containing <code>{ top: - , bottom: -, left: -, right: - }</code> </li>
|
||||
|
||||
<li>Ability to add <strong>sticky toast</strong></li>
|
||||
|
||||
<li>Optional <strong>stack length can be defined</strong> (i.e. maximum number of toasts that can be shown at once)</li>
|
||||
|
||||
</ul>
|
||||
|
||||
Please report any bugs or features you would like added.
|
||||
|
||||
# Copyright
|
||||
|
||||
MIT © [Kamran Ahmed](http://kamranahmed.info)
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
{
|
||||
"name": "jquery-toast-plugin",
|
||||
"description": "A highly customizable jquery toast plugin",
|
||||
"version": "1.3.1",
|
||||
"main": [
|
||||
"./dist/jquery.toast.min.js",
|
||||
"./dist/jquery.toast.min.css"
|
||||
],
|
||||
"moduleType": [],
|
||||
"keywords": [
|
||||
"jquery",
|
||||
"toast-plugin",
|
||||
"jquery-toasts",
|
||||
"toast",
|
||||
"notification",
|
||||
"messages",
|
||||
"jquery-notification"
|
||||
],
|
||||
"authors": [
|
||||
"Kamran Ahmed"
|
||||
],
|
||||
"license": "MIT",
|
||||
"homepage": "http://kamranahmed.info/toast",
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"node_modules",
|
||||
"bower_components",
|
||||
"test",
|
||||
"tests",
|
||||
"README.md"
|
||||
],
|
||||
"dependencies": {
|
||||
"jquery": ">=1.9.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
/**
|
||||
* jQuery toast plugin created by Kamran Ahmed copyright MIT license 2014
|
||||
*/
|
||||
.jq-toast-wrap { display: block; position: fixed; width: 250px; pointer-events: none !important; margin: 0; padding: 0; letter-spacing: normal; z-index: 9000 !important; }
|
||||
.jq-toast-wrap * { margin: 0; padding: 0; }
|
||||
|
||||
.jq-toast-wrap.bottom-left { bottom: 20px; left: 20px; }
|
||||
.jq-toast-wrap.bottom-right { bottom: 20px; right: 40px; }
|
||||
.jq-toast-wrap.top-left { top: 20px; left: 20px; }
|
||||
.jq-toast-wrap.top-right { top: 20px; right: 40px; }
|
||||
|
||||
.jq-toast-single { display: block; width: 100%; padding: 10px; margin: 0px 0px 5px; border-radius: 4px; font-size: 12px; font-family: arial, sans-serif; line-height: 17px; position: relative; pointer-events: all !important; background-color: #444444; color: white; }
|
||||
|
||||
.jq-toast-single h2 { font-family: arial, sans-serif; font-size: 14px; margin: 0px 0px 7px; background: none; color: inherit; line-height: inherit; letter-spacing: normal; }
|
||||
.jq-toast-single a { color: #eee; text-decoration: none; font-weight: bold; border-bottom: 1px solid white; padding-bottom: 3px; font-size: 12px; }
|
||||
|
||||
.jq-toast-single ul { margin: 0px 0px 0px 15px; background: none; padding:0px; }
|
||||
.jq-toast-single ul li { list-style-type: disc !important; line-height: 17px; background: none; margin: 0; padding: 0; letter-spacing: normal; }
|
||||
|
||||
.close-jq-toast-single { position: absolute; top: 3px; right: 7px; font-size: 14px; cursor: pointer; }
|
||||
|
||||
.jq-toast-loader { display: block; position: absolute; top: -2px; height: 5px; width: 0%; left: 0; border-radius: 5px; background: red; }
|
||||
.jq-toast-loaded { width: 100%; }
|
||||
.jq-has-icon { padding: 10px 10px 10px 50px; background-repeat: no-repeat; background-position: 10px; }
|
||||
.jq-icon-info { background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII='); background-color: #31708f; color: #d9edf7; border-color: #bce8f1; }
|
||||
.jq-icon-warning { background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVEhL5ZSvTsNQFMbXZGICMYGYmJhAQIJAICYQPAACiSDB8AiICQQJT4CqQEwgJvYASAQCiZiYmJhAIBATCARJy+9rTsldd8sKu1M0+dLb057v6/lbq/2rK0mS/TRNj9cWNAKPYIJII7gIxCcQ51cvqID+GIEX8ASG4B1bK5gIZFeQfoJdEXOfgX4QAQg7kH2A65yQ87lyxb27sggkAzAuFhbbg1K2kgCkB1bVwyIR9m2L7PRPIhDUIXgGtyKw575yz3lTNs6X4JXnjV+LKM/m3MydnTbtOKIjtz6VhCBq4vSm3ncdrD2lk0VgUXSVKjVDJXJzijW1RQdsU7F77He8u68koNZTz8Oz5yGa6J3H3lZ0xYgXBK2QymlWWA+RWnYhskLBv2vmE+hBMCtbA7KX5drWyRT/2JsqZ2IvfB9Y4bWDNMFbJRFmC9E74SoS0CqulwjkC0+5bpcV1CZ8NMej4pjy0U+doDQsGyo1hzVJttIjhQ7GnBtRFN1UarUlH8F3xict+HY07rEzoUGPlWcjRFRr4/gChZgc3ZL2d8oAAAAASUVORK5CYII='); background-color: #8a6d3b; color: #fcf8e3; border-color: #faebcc; }
|
||||
.jq-icon-error { background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII='); background-color: #a94442; color: #f2dede; border-color: #ebccd1; }
|
||||
.jq-icon-success { background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg=='); color: #dff0d8; background-color: #3c763d; border-color: #d6e9c6; }
|
||||
|
|
@ -1,987 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Demo - Toast Plugin</title>
|
||||
<link href='http://fonts.googleapis.com/css?family=Roboto+Slab:400,700' rel='stylesheet' type='text/css'>
|
||||
<link rel="stylesheet" href="css/jquery.toast.css">
|
||||
<style type="text/css">
|
||||
* { font-family: 'Roboto Slab', serif; margin: 0; padding: 0; }
|
||||
hr { border: 1px solid #ccc; margin-bottom: 20px; }
|
||||
h1, h2 { margin: 20px 0px 10px; }
|
||||
a { text-decoration: none;}
|
||||
.container { display: block; width: 1200px; margin: auto; }
|
||||
strong { padding-bottom: 1px; border-bottom: 1px dotted; }
|
||||
p { margin: 10px 0px; }
|
||||
code { font-family: monospace; color: #2d2d2d; background: whitesmoke; display: block; padding: 10px; border: 1px solid #ccc; overflow: scroll;}
|
||||
a.eval-js { color: whitesmoke; padding: 5px 10px; display: inline-block; margin-bottom: 10px; background: #2d2d2d; border-radius: 2px; }
|
||||
span.muted { font-size: 17px; color: #8B7373; }
|
||||
span.code { font-family: monospace; color: #2d2d2d; background: whitesmoke; padding: 5px; border: 1px solid #ccc; }
|
||||
div.code-runner { margin: 20px 20px;}
|
||||
ul, ol { margin: 10px 50px; }
|
||||
ul li { margin-bottom: 10px; }
|
||||
.hidden { display: none; }
|
||||
span.k { display: inline-block; width: 175px; }
|
||||
span.c { color: #F7BCBC; padding-left: 30px; }
|
||||
.plugin-options label { display: inline-block; width: 265px; }
|
||||
span.toast-position span.k { display: inline; }
|
||||
.toast-index .muted { display: block; color: #AD9D9D; }
|
||||
.toast-index .muted:hover { color: #333; }
|
||||
.latest-update { padding: 0px 30px; border: 1px dashed; margin: 30px 0; box-sizing: border-box; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1 style="text-align: center; margin: 20px 0px;">Jquery Toast Plugin</h1>
|
||||
<hr>
|
||||
|
||||
<h1>Index</h1>
|
||||
<ul class="toast-index">
|
||||
<li><a href="#quick-demos">Quick Demos</a> <span class="muted">Some quick demos and the code to generate that, if you are in a hurry!</span></li>
|
||||
<li><a href="#toast-generator">Generator</a> <span class="muted">A generator for you to <strong>easily generate the code for the kind of toast you want</strong>, so that <strong>you don't have to go through the documentation!</strong></span></li>
|
||||
<li>
|
||||
<a href="#options">Options</a>
|
||||
<span class="muted">Each of the options is accompanied by a demo explaining that option.</span>
|
||||
<ul>
|
||||
<li><a href="#toast-head">Specifying the heading</a></li>
|
||||
<li><a href="#sticky-toast">Making them sticky</a></li>
|
||||
<li><a href="#toast-timer">Changing the toast hide timer</a></li>
|
||||
<li><a href="#showhide-animation">Changing the show/hide animation</a></li>
|
||||
<li><a href="#closeable-toasts">Making the toast closeable or not</a></li>
|
||||
<li><a href="#toasts-stack">Setting the toast stack</a></li>
|
||||
<li><a href="#toasts-positioning">Positioning the toast</a></li>
|
||||
<li><a href="#toasts-icons">Messages with icons</a></li>
|
||||
<li><a href="#toasts-bg-color">Background & text color</a></li>
|
||||
<li><a href="#toasts-text-alignment">Setting the text alignment</a></li>
|
||||
<li><a href="#toasts-events">Toast Events</a></li>
|
||||
<li><a href="#updating-toasts">Updating Toasts</a></li>
|
||||
<li><a href="#resetting-toasts">Resetting Toasts</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="latest-update">
|
||||
<h1 id="latest-update">Latest Update</h1>
|
||||
<p>Toast loader has been introduced in the latest version. Check the demo below to see it in action</p>
|
||||
<div class="code-runner" style="margin-left: 0px; margin-right: 0px;">
|
||||
<a class="eval-js" href="#">Run code</a>
|
||||
<pre><code>$.toast('Here you can put the text of the toast')</code></pre>
|
||||
</div>
|
||||
|
||||
<p>Loader is enabled by default. In order to disable it or change the color, use the `loader` and `loaderBg` options. Have a look at the demo below</p>
|
||||
|
||||
<div class="code-runner" style="margin-left: 0px; margin-right: 0px;">
|
||||
<a class="eval-js" href="#">Run code</a>
|
||||
<pre><code>$.toast({
|
||||
heading: 'Information',
|
||||
text: 'Loaders are enabled by default. Use `loader`, `loaderBg` to change the default behavior',
|
||||
icon: 'info',
|
||||
loader: true, // Change it to false to disable loader
|
||||
loaderBg: '#9EC600' // To change the background
|
||||
})</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<h1 id="quick-demos">Quick Demos</h1>
|
||||
|
||||
<p>To generate a <strong>most simple toast</strong>, all you have to do is</p>
|
||||
<div class="code-runner">
|
||||
<a class="eval-js" href="#">Run code</a>
|
||||
<pre><code>$.toast('Here you can put the text of the toast')</code></pre>
|
||||
</div>
|
||||
|
||||
<p>There are different kinds of toast types:</p>
|
||||
<div class="code-runner">
|
||||
<a class="eval-js" href="#">Run code</a>
|
||||
<pre><code>$.toast({
|
||||
heading: 'Information',
|
||||
text: 'Now you can add icons to generate different kinds of toasts',
|
||||
showHideTransition: 'slide',
|
||||
icon: 'info'
|
||||
})</code></pre>
|
||||
</div>
|
||||
|
||||
<div class="code-runner">
|
||||
<a class="eval-js" href="#">Run code</a>
|
||||
<pre><code>$.toast({
|
||||
heading: 'Error',
|
||||
text: 'Report any <a href="https://github.com/kamranahmedse/jquery-toast-plugin/issues">issues</a>',
|
||||
showHideTransition: 'fade',
|
||||
icon: 'error'
|
||||
})</code></pre>
|
||||
</div>
|
||||
|
||||
<div class="code-runner">
|
||||
<a class="eval-js" href="#">Run code</a>
|
||||
<pre><code>$.toast({
|
||||
heading: 'Warning',
|
||||
text: 'It is going to be supper easy for you to use ;)',
|
||||
showHideTransition: 'plain',
|
||||
icon: 'warning'
|
||||
})</code></pre>
|
||||
</div>
|
||||
|
||||
<div class="code-runner">
|
||||
<a class="eval-js" href="#">Run code</a>
|
||||
<pre><code>$.toast({
|
||||
heading: 'Success',
|
||||
text: 'And these were just the basic demos! Scroll down to check further details on how to customize the output.',
|
||||
showHideTransition: 'slide',
|
||||
icon: 'success'
|
||||
})</code></pre>
|
||||
</div>
|
||||
|
||||
<h1 id="options">Options</h1>
|
||||
<p>Of course that is not all what you can do using this plugin, there are a lot of other options. Let's start explaining each, one by one</p>
|
||||
<p>You should note that, whenever you are going to use options, you have to pass an <span class="code">options</span> object and specify the text as follows:</p>
|
||||
|
||||
<div class="code-runner">
|
||||
<a href="#" class="eval-js">Run code</a>
|
||||
<pre><code>$.toast({
|
||||
text: 'This will become the toast message'
|
||||
})</code></pre>
|
||||
</div>
|
||||
|
||||
<p>The text can be an array:</p>
|
||||
|
||||
<div class="code-runner">
|
||||
<a href="#" class="eval-js">Run code</a>
|
||||
<pre><code>$.toast({
|
||||
heading: 'How to contribute?!',
|
||||
text: [
|
||||
'Fork the repository',
|
||||
'Improve/extend the functionality',
|
||||
'Create a pull request'
|
||||
],
|
||||
icon: 'info'
|
||||
})</code></pre>
|
||||
</div>
|
||||
|
||||
<p>Or put some HTML in the text</p>
|
||||
|
||||
<div class="code-runner">
|
||||
<a href="#" class="eval-js">Run code</a>
|
||||
<pre><code>$.toast({
|
||||
heading: 'Can I add <em>icons</em>?',
|
||||
text: 'Yes! check this <a href="https://github.com/kamranahmedse/jquery-toast-plugin/commits/master">update</a>.',
|
||||
hideAfter: false,
|
||||
icon: 'success'
|
||||
})</code></pre>
|
||||
</div>
|
||||
|
||||
<h2 id="toast-head"><span class="muted">1.</span> Specifying the heading of toast message</h2>
|
||||
<p>You can use the heading to set the <span class="code">heading</span> property to set the heading of the toast message</p>
|
||||
<div class="code-runner">
|
||||
<a href="#" class="eval-js">Run Code</a>
|
||||
<pre><code>$.toast({
|
||||
heading: 'Headings',
|
||||
text: 'You can use the `heading` property to specify the heading of the toast message.',
|
||||
})</code></pre>
|
||||
</div>
|
||||
|
||||
<h2 id="sticky-toast"><span class="muted">2.</span> Making them sticky:</h2>
|
||||
<p>There will be times, when you will want to have <strong>sticky toasts</strong>. To make them <strong>sticky</strong>, all you have to do is set the <span class="code">hideAfter</span> to <span class="code">false</span>. Here is a sticky toast</p>
|
||||
|
||||
<div class="code-runner">
|
||||
<a href="#" class="eval-js">Run Code</a>
|
||||
<pre><code>$.toast({
|
||||
text: 'Set the `hideAfter` property to false and the toast will become sticky.',
|
||||
hideAfter: false
|
||||
})</code></pre>
|
||||
</div>
|
||||
|
||||
<p><sup>*</sup> <span class="code">hideAfter</span> property is basically used to set the timer after which the toast will get hidden. But you can set it to false in order to achieve the sticky toasts.</p>
|
||||
|
||||
<h2 id="toast-timer"><span class="muted">3.</span> Changing the toast hide timer</h2>
|
||||
<p>You can use the property from the above option i.e. <span class="code">hideAfter</span> to change the timer after which toast gets hidden. You have to specify the timer in milliseconds</p>
|
||||
|
||||
<div class="code-runner">
|
||||
<a href="#" class="eval-js">Run Code</a>
|
||||
<pre><code>$.toast({
|
||||
text: 'Set the `hideAfter` property to milliseconds and the toast will hide after the specified milli seconds.',
|
||||
hideAfter: 5000 // in milli seconds
|
||||
})</code></pre>
|
||||
</div>
|
||||
|
||||
<h2 id="showhide-animation"><span class="muted">4.</span> Changing the show/hide animation</h2>
|
||||
<p>You can use <span class="code">showHideTransition</span> property to set the animation. Following are the available options:</p>
|
||||
<ul>
|
||||
<li><span class="code">fade</span> for fade transitions</li>
|
||||
<li><span class="code">slide</span> for slide up and down transitions</li>
|
||||
<li><span class="code">plain</span> simple show from and hide to corner transition</li>
|
||||
</ul>
|
||||
|
||||
<div class="code-runner">
|
||||
<a href="#" class="eval-js">Run Code</a>
|
||||
<pre><code>$.toast({
|
||||
text: 'Set the `showHideTransition` property to fade|plain|slide to achieve different transitions',
|
||||
heading: 'Slide transition',
|
||||
showHideTransition: 'slide'
|
||||
})</code></pre>
|
||||
</div>
|
||||
|
||||
<div class="code-runner">
|
||||
<a href="#" class="eval-js">Run Code</a>
|
||||
<pre><code>$.toast({
|
||||
text: 'Set the `showHideTransition` property to fade|plain|slide to achieve different transitions',
|
||||
heading: 'Fade transition',
|
||||
showHideTransition: 'fade'
|
||||
})</code></pre>
|
||||
</div>
|
||||
|
||||
<div class="code-runner">
|
||||
<a href="#" class="eval-js">Run Code</a>
|
||||
<pre><code>$.toast({
|
||||
text: 'Set the `showHideTransition` property to fade|plain|slide to achieve different transitions',
|
||||
heading: 'Plain transition',
|
||||
showHideTransition: 'plain'
|
||||
})</code></pre>
|
||||
</div>
|
||||
|
||||
<h2 id="closeable-toasts"><span class="muted">5.</span> Making the toast closeable or not</h2>
|
||||
<p>You can use <span class="code">allowToastClose</span> to allow the user to close the toast or not. The only thing that this option does is make that little cross button show or hide itself</p>
|
||||
|
||||
<div class="code-runner">
|
||||
<a href="#" class="eval-js">Run Code</a>
|
||||
<pre><code>$.toast({
|
||||
heading: 'Closeable Toast',
|
||||
text: 'Set the `allowToastClose` property to true|false to make the toast closeable or not',
|
||||
allowToastClose: true
|
||||
})</code></pre>
|
||||
</div>
|
||||
|
||||
<div class="code-runner">
|
||||
<a href="#" class="eval-js">Run Code</a>
|
||||
<pre><code>$.toast({
|
||||
heading: 'Non closeable Toast',
|
||||
text: 'Set the `allowToastClose` property to true|false to make the toast closeable or not',
|
||||
allowToastClose: false
|
||||
})</code></pre>
|
||||
</div>
|
||||
|
||||
<h2 id="toasts-stack"><span class="muted">6.</span> Setting the toast stack</h2>
|
||||
<p><span class="code">stack</span> property can be used to specify how many maximum toasts you want to show at any point of time. By default this property is set to 5</p>
|
||||
|
||||
<div class="code-runner">
|
||||
<a href="#" class="eval-js">Run Code</a>
|
||||
<pre><code>$.toast({
|
||||
heading: 'Stack',
|
||||
text: 'If set to a number, it will show that number of toasts at max at a time',
|
||||
stack: 4
|
||||
})</code></pre>
|
||||
</div>
|
||||
|
||||
<div class="code-runner">
|
||||
<a href="#" class="eval-js">Run Code</a>
|
||||
<pre><code>$.toast({
|
||||
heading: 'No stacking',
|
||||
text: 'If set to false, there will be only one toast at once.',
|
||||
stack: false
|
||||
})</code></pre>
|
||||
</div>
|
||||
|
||||
<p><strong>Note</strong> Hit the run button multiple times to test these demos.</p>
|
||||
|
||||
<h2 id="toasts-positioning"><span class="muted">7.</span> Positioning the toast</h2>
|
||||
<p><span class="code">position</span> property can be used to specify the position. There are following predefined positions which you can use:</p>
|
||||
<ul>
|
||||
<li><span class="code">bottom-left</span> value to show the toast at bottom left position</li>
|
||||
<li><span class="code">bottom-right</span> value to show the toast at bottom right position</li>
|
||||
<li><span class="code">bottom-center</span> value to..</li>
|
||||
<li><span class="code">top-right</span> value to..</li>
|
||||
<li><span class="code">top-left</span> value to..</li>
|
||||
<li><span class="code">top-center</span> value to..</li>
|
||||
<li><span class="code">mid-center</span> value to..</li>
|
||||
<li><span class="code">{ top: '-', bottom: '-', left: '-', right: '-' }</span> javascript object with positioning properties as you set in CSS</li>
|
||||
</ul>
|
||||
|
||||
<div class="code-runner">
|
||||
<a href="#" class="eval-js">Run Code</a>
|
||||
<pre><code><span class='hidden'>$.toast().reset('all');</span>$.toast({
|
||||
heading: 'Positioning',
|
||||
text: 'Specify the custom position object or use one of the predefined ones',
|
||||
position: 'bottom-left',
|
||||
stack: false
|
||||
})</code></pre>
|
||||
</div>
|
||||
|
||||
<div class="code-runner">
|
||||
<a href="#" class="eval-js">Run Code</a>
|
||||
<pre><code><span class='hidden'>$.toast().reset('all');</span>$.toast({
|
||||
heading: 'Positioning',
|
||||
text: 'Specify the custom position object or use one of the predefined ones',
|
||||
position: 'bottom-right',
|
||||
stack: false
|
||||
})</code></pre>
|
||||
</div>
|
||||
|
||||
<div class="code-runner">
|
||||
<a href="#" class="eval-js">Run Code</a>
|
||||
<pre><code><span class='hidden'>$.toast().reset('all');</span>$.toast({
|
||||
heading: 'Positioning',
|
||||
text: 'Use the predefined ones, or specify a custom object',
|
||||
position: 'bottom-center',
|
||||
stack: false
|
||||
})</code></pre>
|
||||
</div>
|
||||
|
||||
<div class="code-runner">
|
||||
<a href="#" class="eval-js">Run Code</a>
|
||||
<pre><code><span class='hidden'>$.toast().reset('all');</span>$.toast({
|
||||
heading: 'Positioning',
|
||||
text: 'Use the predefined ones, or specify a custom object',
|
||||
position: 'top-left',
|
||||
stack: false
|
||||
})</code></pre>
|
||||
</div>
|
||||
|
||||
<div class="code-runner">
|
||||
<a href="#" class="eval-js">Run Code</a>
|
||||
<pre><code><span class='hidden'>$.toast().reset('all');</span>$.toast({
|
||||
heading: 'Positioning',
|
||||
text: 'Use the predefined ones, or specify a custom position object.',
|
||||
position: 'top-right',
|
||||
stack: false
|
||||
})</code></pre>
|
||||
</div>
|
||||
|
||||
<div class="code-runner">
|
||||
<a href="#" class="eval-js">Run Code</a>
|
||||
<pre><code><span class='hidden'>$.toast().reset('all');</span>$.toast({
|
||||
heading: 'Positioning',
|
||||
text: 'Use the predefined ones, or specify a custom position object.',
|
||||
position: 'top-center',
|
||||
stack: false
|
||||
})</code></pre>
|
||||
</div>
|
||||
|
||||
<div class="code-runner">
|
||||
<a href="#" class="eval-js">Run Code</a>
|
||||
<pre><code><span class='hidden'>$.toast().reset('all');</span>$.toast({
|
||||
heading: 'Positioning',
|
||||
text: 'Use the predefined ones, or specify a custom position object.',
|
||||
position: 'mid-center',
|
||||
stack: false
|
||||
})</code></pre>
|
||||
</div>
|
||||
|
||||
<div class="code-runner">
|
||||
<a href="#" class="eval-js">Run Code</a>
|
||||
<pre><code><span class='hidden'>$.toast().reset('all');</span>$.toast({
|
||||
heading: 'Positioning',
|
||||
text: 'Use the predefined ones, or specify a custom position object.',
|
||||
position: {
|
||||
left: 120,
|
||||
top: 120
|
||||
},
|
||||
stack: false
|
||||
})</code></pre>
|
||||
</div>
|
||||
|
||||
<p><strong>Note</strong> It should be noted that, once you change the position of toast by using the `position` property, you'll have to reset the position for the next toasts, if you want them to appear at their default position i.e. the bottom left corner. Or else, each new toast generated will be appearing at the last position i.e. where you displayed the last positioned toast. You can reset the toast position by.</p>
|
||||
|
||||
<div class="code-runner">
|
||||
<a href="#" class="eval-js">Run Code</a>
|
||||
<pre><code>$.toast().reset('all');</code></pre>
|
||||
</div>
|
||||
|
||||
<h2 id="toasts-icons"><span class="muted">8.</span> Messages with icons</h2>
|
||||
<p><span class="code">icon</span> property can be used to specify the predefined types of toasts. Following are the predefined types:</p>
|
||||
<ul>
|
||||
<li><span class="code">info</span> generates a toast with information icon</li>
|
||||
<li><span class="code">warning</span> generates a toast with warning icon</li>
|
||||
<li><span class="code">error</span> generates a toast with error icon</li>
|
||||
<li><span class="code">success</span> generates a toast with success icon</li>
|
||||
</ul>
|
||||
|
||||
<div class="code-runner">
|
||||
<a href="#" class="eval-js">Run Code</a>
|
||||
<pre><code>$.toast({
|
||||
heading: 'Warning',
|
||||
text: 'Now you can seemlessly generate warnings using the icon property in the options',
|
||||
icon: 'warning'
|
||||
})</code></pre>
|
||||
</div>
|
||||
|
||||
<div class="code-runner">
|
||||
<a href="#" class="eval-js">Run Code</a>
|
||||
<pre><code>$.toast({
|
||||
heading: 'Success',
|
||||
text: 'Here is some kind of success message with a success icon that you can notice at the left side.',
|
||||
icon: 'success'
|
||||
})</code></pre>
|
||||
</div>
|
||||
|
||||
<div class="code-runner">
|
||||
<a href="#" class="eval-js">Run Code</a>
|
||||
<pre><code>$.toast({
|
||||
heading: 'Error',
|
||||
text: 'An unexpected error occured while trying to show you the toast! ..Just kidding, it is just a message, toast is right in front of you.',
|
||||
icon: 'error'
|
||||
})</code></pre>
|
||||
</div>
|
||||
|
||||
<div class="code-runner">
|
||||
<a href="#" class="eval-js">Run Code</a>
|
||||
<pre><code>$.toast({
|
||||
heading: 'Information',
|
||||
text: 'Now you can add icons to the toasts as well.',
|
||||
icon: 'info'
|
||||
})</code></pre>
|
||||
</div>
|
||||
|
||||
<h2 id="toasts-bg-color"><span class="muted">9.</span> Background & text color</h2>
|
||||
<p><span class="code">bgColor</span> property is used to specify the background color of the toast message. Default is '#444'</p>
|
||||
<p><span class="code">textColor</span> property is used to specify the text color of the toast message. Default is '#eee'</p>
|
||||
|
||||
<div class="code-runner">
|
||||
<a href="#" class="eval-js">Run Code</a>
|
||||
<pre><code>$.toast({
|
||||
heading: 'Colors',
|
||||
text: 'Colors are specified using `bgColor` and `textColor` properties.',
|
||||
bgColor: '#FF1356',
|
||||
textColor: 'white'
|
||||
})</code></pre>
|
||||
</div>
|
||||
|
||||
<h2 id="toasts-text-alignment"><span class="muted">10.</span> Setting the text alignment</h2>
|
||||
<p><span class="code">textAlign</span> property is used to set the alignment of text inside the toast. Permitted values are:</p>
|
||||
<ul>
|
||||
<li><span class="code">left</span></li>
|
||||
<li><span class="code">right</span></li>
|
||||
<li><span class="code">center</span></li>
|
||||
</ul>
|
||||
|
||||
<div class="code-runner">
|
||||
<a href="#" class="eval-js">Run Code</a>
|
||||
<pre><code>$.toast({
|
||||
text: 'Processing! Please wait..',
|
||||
textAlign: 'center'
|
||||
})</code></pre>
|
||||
</div>
|
||||
|
||||
<h2 id="toasts-class"><span class="muted">9.</span> Custom Classes </h2>
|
||||
<p><span class="code">class</span> property is used to add custom classes to the toast element</p>
|
||||
<style type="text/css">
|
||||
.larger-font {
|
||||
font-size: larger;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="code-runner">
|
||||
<a href="#" class="eval-js">Run Code</a>
|
||||
<pre><code>$.toast({
|
||||
heading: 'Custom Classes',
|
||||
text: 'Custom classes are specified using the `class` option.',
|
||||
class: 'larger-font'
|
||||
})</code></pre>
|
||||
</div>
|
||||
|
||||
<h2 id="toasts-events"><span class="muted">11.</span> Toast Events</h2>
|
||||
<p>Toast exposes the following events for you to bind to whatever you want</p>
|
||||
<ul>
|
||||
<li><span class="code">beforeShow</span> will be triggered right before the toast is about to appear</li>
|
||||
<li><span class="code">afterShown</span> will be triggered after the toast has appeared</li>
|
||||
<li><span class="code">beforeHide</span> will be triggered before the toast is about to hide</li>
|
||||
<li><span class="code">afterHidden</span> will be triggered right after the toast gets hidden</li>
|
||||
</ul>
|
||||
|
||||
<div class="code-runner">
|
||||
<a href="#" class="eval-js"><span class='hidden'>$.toast().reset('all');</span>Run Code</a>
|
||||
<pre><code>$.toast({
|
||||
text: 'Triggers the events',
|
||||
|
||||
beforeShow: function () {
|
||||
alert('The toast is about to appear');
|
||||
},
|
||||
|
||||
afterShown: function () {
|
||||
alert('Toast has appeared.');
|
||||
},
|
||||
|
||||
beforeHide: function () {
|
||||
alert('Toast is about to hide.');
|
||||
},
|
||||
|
||||
afterHidden: function () {
|
||||
alert('Toast has been hidden.');
|
||||
}
|
||||
})</code></pre>
|
||||
</div>
|
||||
|
||||
<h2 id="updating-toasts"><span class="muted">12.</span> Updating Toasts</h2>
|
||||
<p>If you have a reference to a toast and want to update that, you can do so by calling the <span class="code">update</span> method on the instance.</p>
|
||||
|
||||
<div class="code-runner">
|
||||
<a href="#" class="eval-js">Run Code</a>
|
||||
<pre><code>
|
||||
var myToast = $.toast({
|
||||
heading: 'Information',
|
||||
text: 'Here is some information that will be later on turned to an error',
|
||||
icon: 'info',
|
||||
hideAfter: false
|
||||
});
|
||||
|
||||
// Update the toast after three seconds.
|
||||
window.setTimeout(function(){
|
||||
myToast.update({
|
||||
heading: 'Error',
|
||||
text: 'Here is an information that changed to error',
|
||||
icon: 'error',
|
||||
hideAfter: false
|
||||
});
|
||||
}, 3000)
|
||||
|
||||
</code></pre>
|
||||
</div>
|
||||
|
||||
<h2 id="resetting-toasts"><span class="muted">13.</span> Resetting Toasts</h2>
|
||||
<p>If you have the reference to a specific toast, you can reset that by doing the following</p>
|
||||
|
||||
<div class="code-runner">
|
||||
<pre><code>
|
||||
var myToast = $.toast('Some toast that needs to be removed.');
|
||||
myToast.reset(); // remove the toast "Some toast that needs to be removed"
|
||||
</code></pre>
|
||||
</div>
|
||||
|
||||
<p>If you do not have the reference to a specific toast and want to reset every toast, do the following:</p>
|
||||
<div class="code-runner">
|
||||
<pre><code>
|
||||
$.toast().reset('all');
|
||||
</code></pre>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="plugin-options">
|
||||
<h1 id="toast-generator">Customize Plugin</h1>
|
||||
|
||||
<p>
|
||||
<label for="toast-text">Text</label>
|
||||
<input type="text" id="toast-text" class="toast-text" value="Don't forget to star the repository if you like it.">
|
||||
</p>
|
||||
<p>
|
||||
<label for="toast-heading">Heading</label>
|
||||
<input type="text" id="toast-heading" class="toast-heading" value="Note">
|
||||
</p>
|
||||
<p>
|
||||
<label for="toast-transition">Transition</label>
|
||||
<select name="toast-transition" id="toast-transition" class="toast-transition">
|
||||
<option value="fade">Fade</option>
|
||||
<option value="slide">Slide</option>
|
||||
<option value="plain">Plain</option>
|
||||
</select>
|
||||
</p>
|
||||
<p>
|
||||
<label for="allow-toast-close">Allow Toast Close</label>
|
||||
<select name="allow-toast-close" id="allow-toast-close" class="allow-toast-close">
|
||||
<option value="true">True</option>
|
||||
<option value="false">False</option>
|
||||
</select>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label for="auto-hide-toast">Auto Hide</label>
|
||||
<select name="auto-hide-toast" id="auto-hide-toast" class="auto-hide-toast">
|
||||
<option value="true">True</option>
|
||||
<option value="false">False</option>
|
||||
</select>
|
||||
</p>
|
||||
|
||||
<p class="autohide-after sub-item">
|
||||
<label for="autohide-after">Hide (with transition^) after (ms)</label>
|
||||
<input type="text" id="autohide-after" class="autohide-after" value="3000">
|
||||
</p>
|
||||
|
||||
<p class="">
|
||||
<label for="stack-toasts">Stack toasts</label>
|
||||
<select name="stack-toasts" id="stack-toasts" class="stack-toasts">
|
||||
<option value="true">Yes</option>
|
||||
<option value="false">No</option>
|
||||
</select>
|
||||
</p>
|
||||
|
||||
<p class="stack-length sub-item">
|
||||
<label for="stack-length">Stack Length </label>
|
||||
<input type="text" id="stack-length" class="stack-length" value="5">
|
||||
</p>
|
||||
|
||||
<p class="">
|
||||
<label for="toast-position">Toast Position</label>
|
||||
<select name="toast-position" id="toast-position" class="toast-position">
|
||||
<option value="bottom-left">Bottom Left</option>
|
||||
<option value="bottom-right">Bottom Right</option>
|
||||
<option value="top-left">Top Left</option>
|
||||
<option value="top-right">Top Right</option>
|
||||
<option value="top-center">Top Center</option>
|
||||
<option value="bottom-center">Bottom Center</option>
|
||||
<option value="mid-center">Mid Center</option>
|
||||
<option value="custom-position">Custom</option>
|
||||
</select>
|
||||
</p>
|
||||
|
||||
<div class="custom-toast-position sub-item" style="display:none;">
|
||||
<label for="custom-toast-position">Custom Toast Position</label>
|
||||
<ul>
|
||||
<li>
|
||||
<label for="left-position">Left</label>
|
||||
<input type="text" class="left-position" id="left-position">
|
||||
</li>
|
||||
<li>
|
||||
<label for="right-position">Right</label>
|
||||
<input type="text" class="right-position" id="right-position">
|
||||
</li>
|
||||
<li>
|
||||
<label for="top-position">Top</label>
|
||||
<input type="text" class="top-position" id="top-position">
|
||||
</li>
|
||||
<li>
|
||||
<label for="bottom-position">Bottom</label>
|
||||
<input type="text" class="bottom-position" id="bottom-position">
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<p class="">
|
||||
<label for="text-align">Icon</label>
|
||||
<select name="icon-type" id="icon-type" class="text-align">
|
||||
<option value="">-- No icon --</option>
|
||||
<option selected="selected" value="warning">Warning</option>
|
||||
<option value="success">Success</option>
|
||||
<option value="error">Error</option>
|
||||
<option value="info">Information</option>
|
||||
</select>
|
||||
</p>
|
||||
|
||||
<div class="custom-color-info" style="display: none;">
|
||||
<p>
|
||||
<label for="toast-bg">Background Color</label>
|
||||
<input type="color" id="toast-bg" class="toast-bg" value="#444444">
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label for="toast-text-color">Text Color</label>
|
||||
<input type="color" id="toast-text-color" class="toast-text-color" value="#eeeeee">
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<p class="">
|
||||
<label for="text-align">Text Alignment</label>
|
||||
<select name="text-align" id="text-align" class="text-align">
|
||||
<option value="left">Left</option>
|
||||
<option value="right">Right</option>
|
||||
<option value="center">Center</option>
|
||||
</select>
|
||||
</p>
|
||||
|
||||
<p class="">
|
||||
<label for="add-toast-events">Toast Events</label>
|
||||
<select name="add-toast-events" id="add-toast-events" class="add-toast-events">
|
||||
<option value="true">True</option>
|
||||
<option value="false">False</option>
|
||||
</select>
|
||||
</p>
|
||||
|
||||
<p class="">
|
||||
<label for="show-loader">Show Loader</label>
|
||||
<select name="show-loader" id="show-loader" class="show-loader">
|
||||
<option value="true">True</option>
|
||||
<option value="false">False</option>
|
||||
</select>
|
||||
</p>
|
||||
<p>
|
||||
<label for="loader-bg">Loader Color</label>
|
||||
<input type="color" id="loader-bg" class="loader-bg" value="#9EC600">
|
||||
</p>
|
||||
|
||||
|
||||
<div class="code-runner">
|
||||
<a href="#" class="btn generate-toast eval-js">Generate</a>
|
||||
<pre style="padding:0px; background: #f0f3f3;"><code style="margin:0px;" class="highlight">
|
||||
<span class="nd">$</span>.<span class="nf">toast</span>({
|
||||
<span class="toast-text-line"><span class="k">text</span>: "<span class="toast-text s">Hey there fellas, here is a simple toast. Change the options above and then see the code that generates that toast</span>", <span class="c">// Text that is to be shown in the toast</span></span>
|
||||
<span class="toast-heading-line"><span class="k">heading</span>: '<span class="toast-heading s">How to use</span>', <span class="c">// Optional heading to be shown on the toast</span></span>
|
||||
<span class="toast-icon-line"><span class="k">icon</span>: '<span class="toast-icon s">warning</span>', <span class="c">// Type of toast icon</span></span>
|
||||
<span class="toast-transition-line"><span class="k">showHideTransition</span>: '<span class="toast-transition s">fade</span>', <span class="c">// fade, slide or plain</span></span>
|
||||
<span class="toast-allowToastClose-line"><span class="k">allowToastClose</span>: <spna class="kt toast-allowToastClose">true</spna>, <span class="c">// Boolean value <span class="kt">true</span> or <span class="kt">false</span></span></span>
|
||||
<span class="toast-hideAfter-line"><span class="k">hideAfter</span>: <span class="n toast-hideAfter">3000</span>, <span class="c">// <span class="kt">false</span> to make it sticky or number representing the miliseconds as time after which toast needs to be hidden</span></span>
|
||||
<span class="toast-stackLength-line"><span class="k">stack</span>: <span class="n toast-stackLength">5</span>, <span class="c">// <span class="kt">false</span> if there should be only one toast at a time or a number representing the maximum number of toasts to be shown at a time</span></span>
|
||||
<span class="toast-position-string-line"><span class="k">position</span>: '<span class="s toast-position">bottom-left</span>', <span class="c">// bottom-left or bottom-right or bottom-center or top-left or top-right or top-center or mid-center or an object representing the left, right, top, bottom values</span></span>
|
||||
<span class="toast-position-string-obj"><span class="k">position</span>: <span class="s toast-position">{ <span class="k">left</span> : <span class="n toast-position-left">20</span>, <span class="k">right</span> : <span class="n toast-position-right">20</span>, <span class="k">top</span> : <span class="n toast-position-top">20</span>, <span class="k">bottom</span> : <span class="n toast-position-bottom">20</span> }</span>, <span class="c">// bottom-left or bottom-right or bottom-center or top-left or top-right or top-center or mid-center or an object representing the left, right, top, bottom values</span></span>
|
||||
<span class="toast-bgColor-line" style="display: none;"><span class="k">bgColor</span>: '<span class="s toast-bgColor">#444</span>', <span class="c"> // Background color of the toast</span></span>
|
||||
<span class="toast-textColor-line" style="display: none;"><span class="k">textColor</span>: '<span class="s toast-textColor">#eee</span>', <span class="c"> // Text color of the toast</span></span>
|
||||
<span class="toast-textAlign-line"><span class="k">textAlign</span>: '<span class="s toast-textAlign">left</span>', <span class="c"> // Text alignment i.e. left, right or center</span></span>
|
||||
<span class="toast-loader-line"><span class="k">loader</span>: <span class="s toast-textLoader">true</span>, <span class="c"> // Whether to show loader or not. True by default</span></span>
|
||||
<span class="toast-loaderBg-line"><span class="k">loaderBg</span>: '<span class="s toast-textLoaderBg">#9EC600</span>', <span class="c"> // Background color of the toast loader</span></span>
|
||||
<span class="toast-beforeShow-line"><span class="nb k">beforeShow</span>: <span class="nf toast-beforeShow">function ()</span> {}, <span class="c">// will be triggered before the toast is shown</span></span>
|
||||
<span class="toast-afterShown-line"><span class="nb k">afterShown</span>: <span class="nf toast-afterShown">function ()</span> {}, <span class="c">// will be triggered after the toat has been shown</span></span>
|
||||
<span class="toast-beforeHide-line"><span class="nb k">beforeHide</span>: <span class="nf toast-beforeHide">function ()</span> {}, <span class="c">// will be triggered before the toast gets hidden</span></span>
|
||||
<span class="toast-afterHidden-line"><span class="nb k">afterHidden</span>: <span class="nf toast-afterHidden">function ()</span> {} <span class="c"> // will be triggered after the toast has been hidden</span></span>
|
||||
});
|
||||
</code></pre>
|
||||
|
||||
</div>
|
||||
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="js/jquery.toast.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
|
||||
$('.eval-js').on('click', function ( e ) {
|
||||
e.preventDefault();
|
||||
|
||||
if ( !$(this).hasClass('generate-toast') ) {
|
||||
var code = $(this).siblings('pre').find('code').text();
|
||||
code.replace("<span class='hidden'>", '');
|
||||
code.replace("</span");
|
||||
|
||||
eval( code );
|
||||
};
|
||||
});
|
||||
|
||||
$('#icon-type').on('change', function () {
|
||||
if ( !$(this).val() ) {
|
||||
$('.custom-color-info').show();
|
||||
$('.toast-icon-line').hide();
|
||||
$('.toast-bgColor-line').show();
|
||||
$('.toast-textColor-line').show();
|
||||
} else {
|
||||
$('.toast-icon-line').show();
|
||||
$('.custom-color-info').hide();
|
||||
$('.toast-bgColor-line').hide();
|
||||
$('.toast-textColor-line').hide();
|
||||
$('.toast-icon-line span.toast-icon').text( $(this).val() );
|
||||
}
|
||||
});
|
||||
|
||||
// You are about to see some extremely horrible code that can be MUCH MUCH improved,
|
||||
// I've knowlingly done it that way, please don't judge me based upon this ;)
|
||||
$(document).ready(function () {
|
||||
|
||||
function generateCode () {
|
||||
var text = $('.plugin-options #toast-text').val();
|
||||
var heading = $('.plugin-options #toast-heading').val();
|
||||
var transition = $('.toast-transition').val();
|
||||
var allowToastClose = $('#allow-toast-close').val();
|
||||
var autoHide = $('#auto-hide-toast').val();
|
||||
var stackToasts = $('#stack-toasts').val();
|
||||
var toastPosition = $('#toast-position').val()
|
||||
var toastBg = $('#toast-bg').val();
|
||||
var toastTextColor = $('#toast-text-color').val();
|
||||
var toastIcon = $('#icon-type').val();
|
||||
var textAlign = $('#text-align').val();
|
||||
var toastEvents = $('#add-toast-events').val();
|
||||
var loader = $('#show-loader').val();
|
||||
var loaderBg = $('#loader-bg').val();
|
||||
|
||||
if ( text ) {
|
||||
$('.toast-text-line').show();
|
||||
$('.toast-text-line .toast-text').text( text );
|
||||
} else {
|
||||
$('.toast-text-line').hide()
|
||||
$('.toast-text-line .toast-text').text('');
|
||||
};
|
||||
|
||||
if ( heading ) {
|
||||
$('.toast-heading-line').show();
|
||||
$('.toast-heading-line .toast-heading').text( heading );
|
||||
} else {
|
||||
$('.toast-heading-line').hide()
|
||||
$('.toast-heading-line .toast-heading').text('');
|
||||
};
|
||||
|
||||
if ( transition ) {
|
||||
$('.toast-transition-line').show()
|
||||
$('.toast-transition-line .toast-transition').text( transition );
|
||||
} else {
|
||||
$('.toast-transition-line').hide();
|
||||
$('.toast-transition-line .toast-transition').text('fade');
|
||||
}
|
||||
|
||||
if ( allowToastClose ) {
|
||||
$('.toast-allowToastClose-line').show();
|
||||
$('.toast-allowToastClose-line .toast-allowToastClose').text( allowToastClose );
|
||||
} else {
|
||||
$('.toast-allowToastClose-line').hide();
|
||||
$('.toast-allowToastClose-line .toast-allowToastClose').text( false );
|
||||
}
|
||||
|
||||
if ( autoHide && ( autoHide == 'false' ) ) {
|
||||
$('.toast-hideAfter-line').show();
|
||||
$('.toast-hideAfter-line .toast-hideAfter').text('false');
|
||||
$('.autohide-after').hide();
|
||||
} else {
|
||||
$('.toast-hideAfter-line').show();
|
||||
$('.toast-hideAfter-line .toast-hideAfter').text( $('#autohide-after').val() ? $('#autohide-after').val() : 3000 );
|
||||
$('.autohide-after').show();
|
||||
}
|
||||
|
||||
if ( stackToasts && stackToasts != 'true') {
|
||||
$('.toast-stackLength-line').show();
|
||||
$('.toast-stackLength-line .toast-stackLength').text( stackToasts );
|
||||
$('.stack-length').hide();
|
||||
} else {
|
||||
$('.stack-length').show();
|
||||
$('.toast-stackLength-line').show();
|
||||
$('.toast-stackLength-line .toast-stackLength').text( $('#stack-length').val() ? $('#stack-length').val() : 5 );
|
||||
}
|
||||
|
||||
if ( toastPosition && ( toastPosition !== 'custom-position' ) ) {
|
||||
$('.toast-position-string-line').show();
|
||||
$('.custom-toast-position').hide();
|
||||
$('.toast-position-string-line .toast-position').text( toastPosition );
|
||||
} else {
|
||||
$('.toast-position-string-line').hide();
|
||||
$('.toast-position-string-line .toast-position').text('');
|
||||
}
|
||||
|
||||
if ( toastPosition && ( toastPosition === 'custom-position' ) ) {
|
||||
$('.custom-toast-position').show();
|
||||
$('.toast-position-string-obj').show();
|
||||
var left = $('#left-position').val() ? $('#left-position').val() : 'auto';
|
||||
var right = $('#right-position').val() ? $('#right-position').val() : 'auto';
|
||||
var top = $('#top-position').val() ? $('#top-position').val() : 'auto';
|
||||
var bottom = $('#bottom-position').val() ? $('#bottom-position').val() : 'auto';
|
||||
$('.toast-position-string-obj .toast-position-left').text( ( left !== 'auto' ) ? left : "'" + left + "'" );
|
||||
$('.toast-position-string-obj .toast-position-right').text( ( right !== 'auto' ) ? right : "'" + right + "'" );
|
||||
$('.toast-position-string-obj .toast-position-top').text( ( top !== 'auto' ) ? top : "'" + top + "'" );
|
||||
$('.toast-position-string-obj .toast-position-bottom').text( ( bottom !== 'auto' ) ? bottom : "'" + bottom + "'" );
|
||||
} else {
|
||||
$('.toast-position-string-obj').hide();
|
||||
// $('.toast-position-string-obj toast-position').text('');
|
||||
}
|
||||
|
||||
if ( !toastIcon ) {
|
||||
if ( toastBg ) {
|
||||
$('.toast-bgColor-line').show();
|
||||
$('.toast-bgColor-line .toast-bgColor').text( toastBg );
|
||||
} else {
|
||||
$('.toast-bgColor-line').hide();
|
||||
$('.toast-bgColor-line .toast-bgColor').text('');
|
||||
}
|
||||
|
||||
if ( toastTextColor ) {
|
||||
$('.toast-textColor-line').show();
|
||||
$('.toast-textColor-line .toast-textColor').text( toastTextColor );
|
||||
} else {
|
||||
$('.toast-textColor-line').hide();
|
||||
$('.toast-textColor-line .toast-textColor').text('');
|
||||
}
|
||||
}
|
||||
|
||||
if ( textAlign ) {
|
||||
$('.toast-textAlign-line').show();
|
||||
$('.toast-textAlign-line .toast-textAlign').text( textAlign );
|
||||
} else {
|
||||
$('.toast-textAlign-line').hide();
|
||||
$('.toast-textAlign-line .toast-textAlign').text( '');
|
||||
}
|
||||
|
||||
if (loader == 'false') {
|
||||
$('.toast-textLoader').html('false');
|
||||
} else {
|
||||
$('.toast-textLoader').html('true');
|
||||
}
|
||||
|
||||
if (loaderBg) {
|
||||
$('.toast-textLoaderBg').html(loaderBg);
|
||||
}
|
||||
|
||||
if ( toastEvents == 'false' ) {
|
||||
$('.toast-beforeShow-line').hide();
|
||||
$('.toast-afterShown-line').hide();
|
||||
$('.toast-beforeHide-line').hide();
|
||||
$('.toast-afterHidden-line').hide();
|
||||
} else {
|
||||
$('.toast-beforeShow-line').show();
|
||||
$('.toast-afterShown-line').show();
|
||||
$('.toast-beforeHide-line').show();
|
||||
$('.toast-afterHidden-line').show();
|
||||
}
|
||||
}
|
||||
|
||||
$('#top-position').on('change', function () { $('#bottom-position').val('auto'); });
|
||||
$('#bottom-position').on('change', function () { $('#top-position').val('auto'); });
|
||||
$('#left-position').on('change', function () { $('#right-position').val('auto'); });
|
||||
$('#right-position').on('change', function () {$('#left-position').val('auto'); });
|
||||
$('.plugin-options :input').on('change', function () {
|
||||
$.toast().reset('all');
|
||||
generateCode();
|
||||
});
|
||||
|
||||
$('.generate-toast').on('click', function( e ) {
|
||||
e.preventDefault();
|
||||
generateToast();
|
||||
});
|
||||
|
||||
function generateToast () {
|
||||
var options = {};
|
||||
|
||||
if ( $('.toast-text-line').is(':visible') ) {
|
||||
options.text = $('.toast-text-line .toast-text').text();
|
||||
}
|
||||
|
||||
if ( $('.toast-heading-line').is(':visible') ) {
|
||||
options.heading = $('.toast-heading').text();
|
||||
};
|
||||
|
||||
if ( $('.toast-transition-line').is(':visible') ) {
|
||||
options.showHideTransition = $('.toast-transition-line .toast-transition').text();
|
||||
};
|
||||
|
||||
if ( $('.toast-allowToastClose-line').is(':visible') ) {
|
||||
options.allowToastClose = ( $('.toast-allowToastClose-line .toast-allowToastClose').text() === 'true' ) ? true : false;
|
||||
};
|
||||
|
||||
if ( $('.toast-hideAfter-line').is(':visible') ) {
|
||||
options.hideAfter = parseInt($('.toast-hideAfter-line .toast-hideAfter').text(), 10) || false;
|
||||
};
|
||||
|
||||
if ( $('.toast-stackLength-line').is(':visible') ) {
|
||||
options.stack = parseInt($('.toast-stackLength-line .toast-stackLength').text(), 10) || false;
|
||||
};
|
||||
|
||||
if ( $('.toast-position-string-line').is(':visible') ) {
|
||||
options.position = $('.toast-position-string-line .toast-position').text();
|
||||
};
|
||||
|
||||
if ( $('.toast-position-string-obj').is(':visible') ) {
|
||||
options.position = {};
|
||||
options.position.left = parseFloat( $('.toast-position .toast-position-left').text() ) || 'auto';
|
||||
options.position.right = parseFloat( $('.toast-position .toast-position-right').text() ) || 'auto';
|
||||
options.position.top = parseFloat( $('.toast-position .toast-position-top').text() ) || 'auto';
|
||||
options.position.bottom = parseFloat( $('.toast-position .toast-position-bottom').text() ) || 'auto';
|
||||
};
|
||||
|
||||
if ( $('.toast-icon-line').is(':visible') ) {
|
||||
options.icon = $('.toast-icon-line .toast-icon').text();
|
||||
};
|
||||
|
||||
if ( $('.toast-bgColor-line').is(':visible') ) {
|
||||
options.bgColor = $('#toast-bg').val();
|
||||
};
|
||||
|
||||
if ( $('.toast-text-color').is(':visible') ) {
|
||||
options.textColor = $('#toast-text-color').val();
|
||||
};
|
||||
|
||||
if ( $("#text-align").is(':visible') ) {
|
||||
options.textAlign = $('#text-align').val();
|
||||
};
|
||||
|
||||
options.loader = $('.toast-textLoader').html() === 'false' ? false : true;
|
||||
options.loaderBg = $('.toast-textLoaderBg').html();
|
||||
|
||||
$.toast( options );
|
||||
}
|
||||
|
||||
generateCode();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,357 +0,0 @@
|
|||
// jQuery toast plugin created by Kamran Ahmed copyright MIT license 2015
|
||||
if ( typeof Object.create !== 'function' ) {
|
||||
Object.create = function( obj ) {
|
||||
function F() {}
|
||||
F.prototype = obj;
|
||||
return new F();
|
||||
};
|
||||
}
|
||||
|
||||
(function( $, window, document, undefined ) {
|
||||
|
||||
"use strict";
|
||||
|
||||
var Toast = {
|
||||
|
||||
_positionClasses : ['bottom-left', 'bottom-right', 'top-right', 'top-left', 'bottom-center', 'top-center', 'mid-center'],
|
||||
_defaultIcons : ['success', 'error', 'info', 'warning'],
|
||||
|
||||
init: function (options, elem) {
|
||||
this.prepareOptions(options, $.toast.options);
|
||||
this.process();
|
||||
},
|
||||
|
||||
prepareOptions: function(options, options_to_extend) {
|
||||
var _options = {};
|
||||
if ( ( typeof options === 'string' ) || ( options instanceof Array ) ) {
|
||||
_options.text = options;
|
||||
} else {
|
||||
_options = options;
|
||||
}
|
||||
this.options = $.extend( {}, options_to_extend, _options );
|
||||
},
|
||||
|
||||
process: function () {
|
||||
this.setup();
|
||||
this.addToDom();
|
||||
this.position();
|
||||
this.bindToast();
|
||||
this.animate();
|
||||
},
|
||||
|
||||
setup: function () {
|
||||
|
||||
var _toastContent = '';
|
||||
|
||||
this._toastEl = this._toastEl || $('<div></div>', {
|
||||
class : 'jq-toast-single'
|
||||
});
|
||||
|
||||
// For the loader on top
|
||||
_toastContent += '<span class="jq-toast-loader"></span>';
|
||||
|
||||
if ( this.options.allowToastClose ) {
|
||||
_toastContent += '<span class="close-jq-toast-single">×</span>';
|
||||
};
|
||||
|
||||
if ( this.options.text instanceof Array ) {
|
||||
|
||||
if ( this.options.heading ) {
|
||||
_toastContent +='<h2 class="jq-toast-heading">' + this.options.heading + '</h2>';
|
||||
};
|
||||
|
||||
_toastContent += '<ul class="jq-toast-ul">';
|
||||
for (var i = 0; i < this.options.text.length; i++) {
|
||||
_toastContent += '<li class="jq-toast-li" id="jq-toast-item-' + i + '">' + this.options.text[i] + '</li>';
|
||||
}
|
||||
_toastContent += '</ul>';
|
||||
|
||||
} else {
|
||||
if ( this.options.heading ) {
|
||||
_toastContent +='<h2 class="jq-toast-heading">' + this.options.heading + '</h2>';
|
||||
};
|
||||
_toastContent += this.options.text;
|
||||
}
|
||||
|
||||
this._toastEl.html( _toastContent );
|
||||
|
||||
if ( this.options.bgColor !== false ) {
|
||||
this._toastEl.css("background-color", this.options.bgColor);
|
||||
};
|
||||
|
||||
if ( this.options.textColor !== false ) {
|
||||
this._toastEl.css("color", this.options.textColor);
|
||||
};
|
||||
|
||||
if ( this.options.textAlign ) {
|
||||
this._toastEl.css('text-align', this.options.textAlign);
|
||||
}
|
||||
|
||||
if ( this.options.icon !== false ) {
|
||||
this._toastEl.addClass('jq-has-icon');
|
||||
|
||||
if ( $.inArray(this.options.icon, this._defaultIcons) !== -1 ) {
|
||||
this._toastEl.addClass('jq-icon-' + this.options.icon);
|
||||
};
|
||||
};
|
||||
|
||||
if ( this.options.class !== false ){
|
||||
this._toastEl.addClass(this.options.class)
|
||||
}
|
||||
},
|
||||
|
||||
position: function () {
|
||||
if ( ( typeof this.options.position === 'string' ) && ( $.inArray( this.options.position, this._positionClasses) !== -1 ) ) {
|
||||
|
||||
if ( this.options.position === 'bottom-center' ) {
|
||||
this._container.css({
|
||||
left: ( $(window).outerWidth() / 2 ) - this._container.outerWidth()/2,
|
||||
bottom: 20
|
||||
});
|
||||
} else if ( this.options.position === 'top-center' ) {
|
||||
this._container.css({
|
||||
left: ( $(window).outerWidth() / 2 ) - this._container.outerWidth()/2,
|
||||
top: 20
|
||||
});
|
||||
} else if ( this.options.position === 'mid-center' ) {
|
||||
this._container.css({
|
||||
left: ( $(window).outerWidth() / 2 ) - this._container.outerWidth()/2,
|
||||
top: ( $(window).outerHeight() / 2 ) - this._container.outerHeight()/2
|
||||
});
|
||||
} else {
|
||||
this._container.addClass( this.options.position );
|
||||
}
|
||||
|
||||
} else if ( typeof this.options.position === 'object' ) {
|
||||
this._container.css({
|
||||
top : this.options.position.top ? this.options.position.top : 'auto',
|
||||
bottom : this.options.position.bottom ? this.options.position.bottom : 'auto',
|
||||
left : this.options.position.left ? this.options.position.left : 'auto',
|
||||
right : this.options.position.right ? this.options.position.right : 'auto'
|
||||
});
|
||||
} else {
|
||||
this._container.addClass( 'bottom-left' );
|
||||
}
|
||||
},
|
||||
|
||||
bindToast: function () {
|
||||
|
||||
var that = this;
|
||||
|
||||
this._toastEl.on('afterShown', function () {
|
||||
that.processLoader();
|
||||
});
|
||||
|
||||
this._toastEl.find('.close-jq-toast-single').on('click', function ( e ) {
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
if( that.options.showHideTransition === 'fade') {
|
||||
that._toastEl.trigger('beforeHide');
|
||||
that._toastEl.fadeOut(function () {
|
||||
that._toastEl.trigger('afterHidden');
|
||||
});
|
||||
} else if ( that.options.showHideTransition === 'slide' ) {
|
||||
that._toastEl.trigger('beforeHide');
|
||||
that._toastEl.slideUp(function () {
|
||||
that._toastEl.trigger('afterHidden');
|
||||
});
|
||||
} else {
|
||||
that._toastEl.trigger('beforeHide');
|
||||
that._toastEl.hide(function () {
|
||||
that._toastEl.trigger('afterHidden');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if ( typeof this.options.beforeShow == 'function' ) {
|
||||
this._toastEl.on('beforeShow', function () {
|
||||
that.options.beforeShow();
|
||||
});
|
||||
};
|
||||
|
||||
if ( typeof this.options.afterShown == 'function' ) {
|
||||
this._toastEl.on('afterShown', function () {
|
||||
that.options.afterShown();
|
||||
});
|
||||
};
|
||||
|
||||
if ( typeof this.options.beforeHide == 'function' ) {
|
||||
this._toastEl.on('beforeHide', function () {
|
||||
that.options.beforeHide();
|
||||
});
|
||||
};
|
||||
|
||||
if ( typeof this.options.afterHidden == 'function' ) {
|
||||
this._toastEl.on('afterHidden', function () {
|
||||
that.options.afterHidden();
|
||||
});
|
||||
};
|
||||
},
|
||||
|
||||
addToDom: function () {
|
||||
|
||||
var _container = $('.jq-toast-wrap');
|
||||
|
||||
if ( _container.length === 0 ) {
|
||||
|
||||
_container = $('<div></div>',{
|
||||
class: "jq-toast-wrap"
|
||||
});
|
||||
|
||||
$('body').append( _container );
|
||||
|
||||
} else if ( !this.options.stack || isNaN( parseInt(this.options.stack, 10) ) ) {
|
||||
_container.empty();
|
||||
}
|
||||
|
||||
_container.find('.jq-toast-single:hidden').remove();
|
||||
|
||||
_container.append( this._toastEl );
|
||||
|
||||
if ( this.options.stack && !isNaN( parseInt( this.options.stack ), 10 ) ) {
|
||||
|
||||
var _prevToastCount = _container.find('.jq-toast-single').length,
|
||||
_extToastCount = _prevToastCount - this.options.stack;
|
||||
|
||||
if ( _extToastCount > 0 ) {
|
||||
$('.jq-toast-wrap').find('.jq-toast-single').slice(0, _extToastCount).remove();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
this._container = _container;
|
||||
},
|
||||
|
||||
canAutoHide: function () {
|
||||
return ( this.options.hideAfter !== false ) && !isNaN( parseInt( this.options.hideAfter, 10 ) );
|
||||
},
|
||||
|
||||
processLoader: function () {
|
||||
// Show the loader only, if auto-hide is on and loader is demanded
|
||||
if (!this.canAutoHide() || this.options.loader === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var loader = this._toastEl.find('.jq-toast-loader');
|
||||
|
||||
// 400 is the default time that jquery uses for fade/slide
|
||||
// Divide by 1000 for milliseconds to seconds conversion
|
||||
var transitionTime = (this.options.hideAfter - 400) / 1000 + 's';
|
||||
var loaderBg = this.options.loaderBg;
|
||||
|
||||
var style = loader.attr('style') || '';
|
||||
style = style.substring(0, style.indexOf('-webkit-transition')); // Remove the last transition definition
|
||||
|
||||
style += '-webkit-transition: width ' + transitionTime + ' ease-in; \
|
||||
-o-transition: width ' + transitionTime + ' ease-in; \
|
||||
transition: width ' + transitionTime + ' ease-in; \
|
||||
background-color: ' + loaderBg + ';';
|
||||
|
||||
|
||||
loader.attr('style', style).addClass('jq-toast-loaded');
|
||||
},
|
||||
|
||||
animate: function () {
|
||||
|
||||
var that = this;
|
||||
|
||||
this._toastEl.hide();
|
||||
|
||||
this._toastEl.trigger('beforeShow');
|
||||
|
||||
if ( this.options.showHideTransition.toLowerCase() === 'fade' ) {
|
||||
this._toastEl.fadeIn(function ( ){
|
||||
that._toastEl.trigger('afterShown');
|
||||
});
|
||||
} else if ( this.options.showHideTransition.toLowerCase() === 'slide' ) {
|
||||
this._toastEl.slideDown(function ( ){
|
||||
that._toastEl.trigger('afterShown');
|
||||
});
|
||||
} else {
|
||||
this._toastEl.show(function ( ){
|
||||
that._toastEl.trigger('afterShown');
|
||||
});
|
||||
}
|
||||
|
||||
if (this.canAutoHide()) {
|
||||
|
||||
var that = this;
|
||||
|
||||
window.setTimeout(function(){
|
||||
|
||||
if ( that.options.showHideTransition.toLowerCase() === 'fade' ) {
|
||||
that._toastEl.trigger('beforeHide');
|
||||
that._toastEl.fadeOut(function () {
|
||||
that._toastEl.trigger('afterHidden');
|
||||
});
|
||||
} else if ( that.options.showHideTransition.toLowerCase() === 'slide' ) {
|
||||
that._toastEl.trigger('beforeHide');
|
||||
that._toastEl.slideUp(function () {
|
||||
that._toastEl.trigger('afterHidden');
|
||||
});
|
||||
} else {
|
||||
that._toastEl.trigger('beforeHide');
|
||||
that._toastEl.hide(function () {
|
||||
that._toastEl.trigger('afterHidden');
|
||||
});
|
||||
}
|
||||
|
||||
}, this.options.hideAfter);
|
||||
};
|
||||
},
|
||||
|
||||
reset: function ( resetWhat ) {
|
||||
|
||||
if ( resetWhat === 'all' ) {
|
||||
$('.jq-toast-wrap').remove();
|
||||
} else {
|
||||
this._toastEl.remove();
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
update: function(options) {
|
||||
this.prepareOptions(options, this.options);
|
||||
this.setup();
|
||||
this.bindToast();
|
||||
}
|
||||
};
|
||||
|
||||
$.toast = function(options) {
|
||||
var toast = Object.create(Toast);
|
||||
toast.init(options, this);
|
||||
|
||||
return {
|
||||
|
||||
reset: function ( what ) {
|
||||
toast.reset( what );
|
||||
},
|
||||
|
||||
update: function( options ) {
|
||||
toast.update( options );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$.toast.options = {
|
||||
text: '',
|
||||
heading: '',
|
||||
showHideTransition: 'fade',
|
||||
allowToastClose: true,
|
||||
hideAfter: 3000,
|
||||
loader: true,
|
||||
loaderBg: '#9EC600',
|
||||
stack: 5,
|
||||
position: 'bottom-left',
|
||||
bgColor: false,
|
||||
textColor: false,
|
||||
textAlign: 'left',
|
||||
icon: false,
|
||||
beforeShow: function () {},
|
||||
afterShown: function () {},
|
||||
beforeHide: function () {},
|
||||
afterHidden: function () {}
|
||||
};
|
||||
|
||||
})( jQuery, window, document );
|
||||
|
|
@ -1 +0,0 @@
|
|||
.jq-toast-wrap,.jq-toast-wrap *{margin:0;padding:0}.jq-toast-wrap{display:block;position:fixed;width:250px;pointer-events:none!important;letter-spacing:normal;z-index:9000!important}.jq-toast-wrap.bottom-left{bottom:20px;left:20px}.jq-toast-wrap.bottom-right{bottom:20px;right:40px}.jq-toast-wrap.top-left{top:20px;left:20px}.jq-toast-wrap.top-right{top:20px;right:40px}.jq-toast-single{display:block;width:100%;padding:10px;margin:0 0 5px;border-radius:4px;font-size:12px;font-family:arial,sans-serif;line-height:17px;position:relative;pointer-events:all!important;background-color:#444;color:#fff}.jq-toast-single h2{font-family:arial,sans-serif;font-size:14px;margin:0 0 7px;background:0 0;color:inherit;line-height:inherit;letter-spacing:normal}.jq-toast-single a{color:#eee;text-decoration:none;font-weight:700;border-bottom:1px solid #fff;padding-bottom:3px;font-size:12px}.jq-toast-single ul{margin:0 0 0 15px;background:0 0;padding:0}.jq-toast-single ul li{list-style-type:disc!important;line-height:17px;background:0 0;margin:0;padding:0;letter-spacing:normal}.close-jq-toast-single{position:absolute;top:3px;right:7px;font-size:14px;cursor:pointer}.jq-toast-loader{display:block;position:absolute;top:-2px;height:5px;width:0;left:0;border-radius:5px;background:red}.jq-toast-loaded{width:100%}.jq-has-icon{padding:10px 10px 10px 50px;background-repeat:no-repeat;background-position:10px}.jq-icon-info{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=);background-color:#31708f;color:#d9edf7;border-color:#bce8f1}.jq-icon-warning{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVEhL5ZSvTsNQFMbXZGICMYGYmJhAQIJAICYQPAACiSDB8AiICQQJT4CqQEwgJvYASAQCiZiYmJhAIBATCARJy+9rTsldd8sKu1M0+dLb057v6/lbq/2rK0mS/TRNj9cWNAKPYIJII7gIxCcQ51cvqID+GIEX8ASG4B1bK5gIZFeQfoJdEXOfgX4QAQg7kH2A65yQ87lyxb27sggkAzAuFhbbg1K2kgCkB1bVwyIR9m2L7PRPIhDUIXgGtyKw575yz3lTNs6X4JXnjV+LKM/m3MydnTbtOKIjtz6VhCBq4vSm3ncdrD2lk0VgUXSVKjVDJXJzijW1RQdsU7F77He8u68koNZTz8Oz5yGa6J3H3lZ0xYgXBK2QymlWWA+RWnYhskLBv2vmE+hBMCtbA7KX5drWyRT/2JsqZ2IvfB9Y4bWDNMFbJRFmC9E74SoS0CqulwjkC0+5bpcV1CZ8NMej4pjy0U+doDQsGyo1hzVJttIjhQ7GnBtRFN1UarUlH8F3xict+HY07rEzoUGPlWcjRFRr4/gChZgc3ZL2d8oAAAAASUVORK5CYII=);background-color:#8a6d3b;color:#fcf8e3;border-color:#faebcc}.jq-icon-error{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII=);background-color:#a94442;color:#f2dede;border-color:#ebccd1}.jq-icon-success{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg==);color:#dff0d8;background-color:#3c763d;border-color:#d6e9c6}
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -1,35 +0,0 @@
|
|||
{
|
||||
"name": "jquery-toast-plugin",
|
||||
"filename": "dist/jquery.toast.min.js",
|
||||
"main": "dist/jquery.toast.min.js",
|
||||
"style": "dist/jquery.toast.min.css",
|
||||
"version": "1.3.2",
|
||||
"description": "Highly customizable jquery plugin to show toast messages",
|
||||
"homepage": "http://www.kamranahmed.info/toast",
|
||||
"keywords": [
|
||||
"Toast",
|
||||
"Toast plugin",
|
||||
"Jquery toast plugin"
|
||||
],
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "Kamran Ahmed",
|
||||
"web": "http://kamranahmed.info"
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/kamranahmedse/jquery-toast-plugin.git"
|
||||
},
|
||||
"bugs": "https://github.com/kamranahmedse/jquery-toast-plugin/issues",
|
||||
"licenses": [
|
||||
{
|
||||
"type": "MIT",
|
||||
"url": "http://www.opensource.org/licenses/mit-license.php"
|
||||
}
|
||||
],
|
||||
"devDependencies": {
|
||||
},
|
||||
"scripts": {
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
{
|
||||
"name": "TuneTales",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
"jquery-toast-plugin": "^1.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/jquery-toast-plugin": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/jquery-toast-plugin/-/jquery-toast-plugin-1.3.2.tgz",
|
||||
"integrity": "sha512-0j/nfqA2FHFuJXp8QL33EVVCY//TDVfq4LULhTbasZYl2aZlX6YiSF5IGrI31dQiS9S4JkXBUfX3rMJcfl/u/g=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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