Initial commit
This commit is contained in:
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
61
README.md
Normal file
61
README.md
Normal file
@@ -0,0 +1,61 @@
|
||||
# Simple File List
|
||||
|
||||
Um plugin simples para WordPress que permite o envio, organização e listagem de arquivos com categorias.
|
||||
|
||||
---
|
||||
|
||||
## Instalação
|
||||
|
||||
1. **Faça upload dos arquivos do plugin** para a pasta:
|
||||
```
|
||||
wp-content/plugins/simple-file-list
|
||||
```
|
||||
2. **Ative o plugin** no painel do WordPress em **Plugins > Plugins instalados**.
|
||||
|
||||
---
|
||||
|
||||
## Como Usar
|
||||
|
||||
### Exibir o gerenciador de arquivos no site
|
||||
|
||||
Adicione o shortcode abaixo em qualquer página ou post onde deseja exibir o gerenciador de arquivos:
|
||||
|
||||
```
|
||||
[simple_file_list]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Funcionalidades
|
||||
|
||||
- **Upload de arquivos** (restrito a usuários logados com permissão)
|
||||
- **Campos de descrição e categoria** para cada arquivo enviado
|
||||
- **Tabela de arquivos** com miniatura, nome, categoria, tamanho, data e ações (abrir/baixar)
|
||||
- **Filtro por categoria** integrado à tabela
|
||||
- **Exclusão de arquivos** (apenas para usuários autorizados)
|
||||
- **Limites configuráveis** de tamanho, quantidade e tipos de arquivos
|
||||
|
||||
---
|
||||
|
||||
## Configurações
|
||||
|
||||
Acesse **Configurações > File List** no menu do WordPress para:
|
||||
|
||||
- Definir o número máximo de arquivos por envio
|
||||
- Definir o tamanho máximo de cada arquivo (MB)
|
||||
- Definir as extensões de arquivos permitidas (ex: `jpg,png,pdf`)
|
||||
|
||||
---
|
||||
|
||||
## Observações
|
||||
|
||||
- Apenas usuários logados com permissão de upload podem enviar ou excluir arquivos.
|
||||
- Os arquivos são armazenados em:
|
||||
`wp-content/uploads/simple-file-list/`
|
||||
- O plugin utiliza as cores e variáveis CSS do tema para melhor integração visual.
|
||||
|
||||
---
|
||||
|
||||
## Suporte
|
||||
|
||||
Para dúvidas ou sugestões, abra uma issue ou entre em contato com
|
278
assets/css/style.css
Normal file
278
assets/css/style.css
Normal file
@@ -0,0 +1,278 @@
|
||||
/* Simple File List Styles */
|
||||
.sfl-upload-container {
|
||||
background: #fff;
|
||||
border-radius: var(--borda-radius);
|
||||
box-shadow: var(--sombra);
|
||||
padding: 25px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.sfl-upload-container h2 {
|
||||
color: var(--azul-principal);
|
||||
margin-top: 0;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.sfl-upload-area {
|
||||
border: 2px dashed var(--azul-claro);
|
||||
border-radius: var(--borda-radius);
|
||||
padding: 30px;
|
||||
text-align: center;
|
||||
transition: var(--transicao);
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.sfl-upload-area:hover {
|
||||
border-color: var(--azul-brilhante);
|
||||
background-color: rgba(0, 166, 251, 0.05);
|
||||
}
|
||||
|
||||
.sfl-browse-btn {
|
||||
background: var(--azul-principal);
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px 20px;
|
||||
border-radius: var(--borda-radius);
|
||||
cursor: pointer;
|
||||
font-weight: 500;
|
||||
transition: var(--transicao);
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.sfl-browse-btn:hover {
|
||||
background: var(--azul-brilhante);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.sfl-upload-details {
|
||||
margin-top: 20px;
|
||||
color: var(--azul-escuro);
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.sfl-upload-details p {
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
.sfl-file-meta {
|
||||
margin-top: 20px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.sfl-meta-fields {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 15px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.sfl-meta-fields label {
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
font-weight: 500;
|
||||
color: var(--azul-escuro);
|
||||
}
|
||||
|
||||
.sfl-meta-fields input {
|
||||
width: 100%;
|
||||
padding: 8px 12px;
|
||||
border: 1px solid var(--cinza);
|
||||
border-radius: var(--borda-radius);
|
||||
transition: var(--transicao);
|
||||
}
|
||||
|
||||
.sfl-meta-fields input:focus {
|
||||
border-color: var(--azul-brilhante);
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 2px rgba(0, 166, 251, 0.2);
|
||||
}
|
||||
|
||||
.sfl-upload-btn {
|
||||
background: var(--verde);
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px 20px;
|
||||
border-radius: var(--borda-radius);
|
||||
cursor: pointer;
|
||||
font-weight: 500;
|
||||
transition: var(--transicao);
|
||||
}
|
||||
|
||||
.sfl-upload-btn:hover {
|
||||
background: #3d8b40;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.sfl-progress {
|
||||
margin-top: 20px;
|
||||
background: var(--cinza);
|
||||
border-radius: 20px;
|
||||
height: 10px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.sfl-progress-bar {
|
||||
background: var(--azul-brilhante);
|
||||
border-radius: 20px;
|
||||
height: 100%;
|
||||
width: 0%;
|
||||
transition: width 0.3s ease;
|
||||
}
|
||||
|
||||
.sfl-progress-text {
|
||||
position: absolute;
|
||||
top: -25px;
|
||||
right: 0;
|
||||
font-size: 0.8rem;
|
||||
color: var(--azul-escuro);
|
||||
}
|
||||
|
||||
.sfl-file-list {
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.sfl-file-list table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
background: white;
|
||||
border-radius: var(--borda-radius);
|
||||
box-shadow: var(--sombra);
|
||||
}
|
||||
|
||||
.sfl-file-list th {
|
||||
background: var(--azul-principal);
|
||||
color: white;
|
||||
padding: 12px 15px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.sfl-file-list th, .sfl-file-list td {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.sfl-file-list td {
|
||||
padding: 12px 15px;
|
||||
border-bottom: 1px solid var(--cinza);
|
||||
}
|
||||
|
||||
.sfl-file-list tr:last-child td {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.sfl-file-list tr:hover {
|
||||
background-color: rgba(0, 100, 148, 0.05);
|
||||
}
|
||||
|
||||
.sfl-file-description {
|
||||
margin: 5px 0 0;
|
||||
color: var(--azul-claro);
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.sfl-file-actions {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.sfl-action-link {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
background: var(--azul-principal);
|
||||
color: #fff !important; /* texto branco */
|
||||
border: none;
|
||||
border-radius: var(--borda-radius);
|
||||
padding: 7px 16px;
|
||||
font-weight: 500;
|
||||
font-size: 0.95rem;
|
||||
text-decoration: none !important; /* remove underline */
|
||||
transition: background 0.2s, box-shadow 0.2s, color 0.2s;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.04);
|
||||
cursor: pointer;
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
.sfl-action-link:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.sfl-action-link:hover {
|
||||
background: var(--azul-brilhante);
|
||||
color: #fff !important; /* mantém texto branco no hover */
|
||||
text-decoration: none !important; /* garante sem underline no hover */
|
||||
box-shadow: 0 2px 8px rgba(0,166,251,0.08);
|
||||
}
|
||||
|
||||
/* Opcional: Adicione ícones usando Dashicons */
|
||||
.sfl-action-link[data-action="abrir"]::before {
|
||||
font-family: "Dashicons";
|
||||
content: "\f179";
|
||||
font-size: 1.1em;
|
||||
margin-right: 4px;
|
||||
}
|
||||
.sfl-action-link[data-action="baixar"]::before {
|
||||
font-family: "Dashicons";
|
||||
content: "\f316";
|
||||
font-size: 1.1em;
|
||||
margin-right: 4px;
|
||||
}
|
||||
.sfl-action-link[data-action="copiar"]::before {
|
||||
font-family: "Dashicons";
|
||||
content: "\f481";
|
||||
font-size: 1.1em;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
/* Drag and drop styles */
|
||||
.sfl-upload-area.drag-over {
|
||||
background-color: rgba(0, 166, 251, 0.1);
|
||||
border-color: var(--azul-brilhante);
|
||||
}
|
||||
|
||||
/* Responsive styles */
|
||||
@media (max-width: 768px) {
|
||||
.sfl-meta-fields {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.sfl-file-actions {
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.sfl-file-icon {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
text-align: center;
|
||||
line-height: 40px;
|
||||
font-size: 32px;
|
||||
color: #0073aa;
|
||||
}
|
||||
|
||||
.sfl-filter-form {
|
||||
margin-bottom: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
background: none;
|
||||
padding: 0;
|
||||
}
|
||||
.sfl-filter-form label {
|
||||
margin: 0;
|
||||
color: var(--azul-principal); /* azul para o label */
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.sfl-filter-form select {
|
||||
padding: 6px 12px;
|
||||
border-radius: var(--borda-radius);
|
||||
border: 1px solid var(--cinza);
|
||||
margin-left: 0;
|
||||
color: #222; /* preto para o texto das opções */
|
||||
background: #fff;
|
||||
font-weight: 500;
|
||||
}
|
155
assets/js/script.js
Normal file
155
assets/js/script.js
Normal file
@@ -0,0 +1,155 @@
|
||||
jQuery(document).ready(function($) {
|
||||
// Handle file selection
|
||||
$('#sfl-browse-btn').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
$('#sfl-file-input').click();
|
||||
});
|
||||
|
||||
$('#sfl-file-input').on('change', function() {
|
||||
const files = this.files;
|
||||
if (files.length > 0) {
|
||||
const fileNames = Array.from(files).map(file => file.name).join(', ');
|
||||
$('#sfl-file-info').text(`${files.length} arquivo(s) selecionado(s): ${fileNames}`);
|
||||
$('.sfl-file-meta').show();
|
||||
} else {
|
||||
$('#sfl-file-info').text('Nenhum arquivo selecionado.');
|
||||
$('.sfl-file-meta').hide();
|
||||
}
|
||||
});
|
||||
|
||||
// Handle drag and drop
|
||||
const dropZone = $('#sfl-drop-zone')[0];
|
||||
|
||||
if (dropZone) {
|
||||
dropZone.addEventListener('dragover', function(e) {
|
||||
e.preventDefault();
|
||||
$(this).addClass('drag-over');
|
||||
});
|
||||
|
||||
dropZone.addEventListener('dragleave', function() {
|
||||
$(this).removeClass('drag-over');
|
||||
});
|
||||
|
||||
dropZone.addEventListener('drop', function(e) {
|
||||
e.preventDefault();
|
||||
$(this).removeClass('drag-over');
|
||||
|
||||
const files = e.dataTransfer.files;
|
||||
if (files.length > 0) {
|
||||
$('#sfl-file-input')[0].files = files;
|
||||
const fileNames = Array.from(files).map(file => file.name).join(', ');
|
||||
$('#sfl-file-info').text(`${files.length} file(s) selected: ${fileNames}`);
|
||||
$('.sfl-file-meta').show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Handle file upload
|
||||
$('#sfl-upload-btn').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const files = $('#sfl-file-input')[0].files;
|
||||
if (!files || files.length === 0) {
|
||||
alert('Selecione pelo menos um arquivo para enviar.');
|
||||
return;
|
||||
}
|
||||
|
||||
const maxFiles = parseInt('<?php echo get_option("sfl_max_files"); ?>');
|
||||
if (files.length > maxFiles) {
|
||||
alert(`Você pode enviar no máximo ${maxFiles} arquivos de uma vez.`);
|
||||
return;
|
||||
}
|
||||
|
||||
const description = $('#sfl-file-description').val();
|
||||
const category = $('#sfl-file-category').val();
|
||||
|
||||
$('.sfl-progress').show();
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('action', 'sfl_upload_file');
|
||||
formData.append('security', sfl_ajax.nonce);
|
||||
formData.append('description', description);
|
||||
formData.append('category', category);
|
||||
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
formData.append('sfl_file_upload', files[i]);
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: sfl_ajax.ajax_url,
|
||||
type: 'POST',
|
||||
data: formData,
|
||||
processData: false,
|
||||
contentType: false,
|
||||
xhr: function() {
|
||||
const xhr = new window.XMLHttpRequest();
|
||||
xhr.upload.addEventListener('progress', function(e) {
|
||||
if (e.lengthComputable) {
|
||||
const percent = Math.round((e.loaded / e.total) * 100);
|
||||
$('.sfl-progress-bar').css('width', percent + '%');
|
||||
$('.sfl-progress-text').text(percent + '%');
|
||||
}
|
||||
}, false);
|
||||
return xhr;
|
||||
},
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
alert('Arquivos enviados com sucesso!');
|
||||
location.reload();
|
||||
} else {
|
||||
alert('Erro: ' + response.data);
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
alert('Erro: ' + error);
|
||||
},
|
||||
complete: function() {
|
||||
$('.sfl-progress').hide();
|
||||
$('.sfl-progress-bar').css('width', '0%');
|
||||
$('.sfl-progress-text').text('0%');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Handle file deletion
|
||||
$('.sfl-delete-file').on('click', function() {
|
||||
if (!confirm('Tem certeza que deseja excluir este arquivo?')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const fileId = $(this).data('file-id');
|
||||
|
||||
$.ajax({
|
||||
url: sfl_ajax.ajax_url,
|
||||
type: 'POST',
|
||||
data: {
|
||||
action: 'sfl_delete_file',
|
||||
security: sfl_ajax.nonce,
|
||||
file_id: fileId
|
||||
},
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
alert('Arquivo excluído com sucesso!');
|
||||
location.reload();
|
||||
} else {
|
||||
alert('Erro: ' + response.data);
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
alert('Erro: ' + error);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Handle copy link
|
||||
$('.sfl-copy-link').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
const fileUrl = $(this).data('file-url');
|
||||
|
||||
navigator.clipboard.writeText(fileUrl).then(function() {
|
||||
alert('Link copiado para a área de transferência!');
|
||||
}, function() {
|
||||
alert('Falha ao copiar o link. Tente novamente.');
|
||||
});
|
||||
});
|
||||
});
|
111
includes/admin.php
Normal file
111
includes/admin.php
Normal file
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
function sfl_admin_page() {
|
||||
?>
|
||||
<div class="wrap">
|
||||
<h1>Lista de Arquivos Simples</h1>
|
||||
|
||||
<?php
|
||||
// Handle form submissions
|
||||
if (isset($_POST['sfl_settings_submit'])) {
|
||||
update_option('sfl_max_files', intval($_POST['max_files']));
|
||||
update_option('sfl_max_size', intval($_POST['max_size']));
|
||||
update_option('sfl_allowed_types', sanitize_text_field($_POST['allowed_types']));
|
||||
|
||||
echo '<div class="notice notice-success"><p>Configurações salvas com sucesso.</p></div>';
|
||||
}
|
||||
?>
|
||||
|
||||
<div class="sfl-admin-container">
|
||||
<div class="sfl-admin-content">
|
||||
<h2>Arquivos Enviados</h2>
|
||||
|
||||
<?php sfl_render_admin_file_list(); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
function sfl_settings_page() {
|
||||
?>
|
||||
<div class="wrap">
|
||||
<h1>Configurações da Lista de Arquivos</h1>
|
||||
|
||||
<form method="post" action="">
|
||||
<table class="form-table">
|
||||
<tr>
|
||||
<th scope="row"><label for="max_files">Máximo de Arquivos</label></th>
|
||||
<td>
|
||||
<input type="number" name="max_files" id="max_files"
|
||||
value="<?php echo esc_attr(get_option('sfl_max_files')); ?>" min="1" max="50">
|
||||
<p class="description">Quantidade máxima de arquivos que podem ser enviados de uma vez.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><label for="max_size">Tamanho Máximo do Arquivo (MB)</label></th>
|
||||
<td>
|
||||
<input type="number" name="max_size" id="max_size"
|
||||
value="<?php echo esc_attr(get_option('sfl_max_size')); ?>" min="1" max="20">
|
||||
<p class="description">Tamanho máximo para cada arquivo enviado em megabytes.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><label for="allowed_types">Tipos de Arquivo Permitidos</label></th>
|
||||
<td>
|
||||
<input type="text" name="allowed_types" id="allowed_types"
|
||||
value="<?php echo esc_attr(get_option('sfl_allowed_types')); ?>">
|
||||
<p class="description">Lista separada por vírgulas das extensões permitidas (ex: jpg,png,pdf).</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<?php submit_button('Salvar Configurações', 'primary', 'sfl_settings_submit'); ?>
|
||||
</form>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
function sfl_render_admin_file_list() {
|
||||
global $wpdb;
|
||||
$table_name = $wpdb->prefix . 'simple_file_list';
|
||||
|
||||
$files = $wpdb->get_results("SELECT * FROM $table_name ORDER BY upload_date DESC");
|
||||
|
||||
if (empty($files)) {
|
||||
echo '<p>Nenhum arquivo foi enviado ainda.</p>';
|
||||
return;
|
||||
}
|
||||
|
||||
?>
|
||||
<div class="sfl-file-list">
|
||||
<table class="wp-list-table widefat fixed striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Nome</th>
|
||||
<th>Tamanho</th>
|
||||
<th>Data</th>
|
||||
<th>Descrição</th>
|
||||
<th>Categoria</th>
|
||||
<th>Ações</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($files as $file): ?>
|
||||
<tr>
|
||||
<td><?php echo esc_html($file->file_name); ?></td>
|
||||
<td><?php echo esc_html($file->file_size); ?></td>
|
||||
<td><?php echo date('d/m/Y', strtotime($file->upload_date)); ?></td>
|
||||
<td><?php echo esc_html($file->description); ?></td>
|
||||
<td><?php echo esc_html($file->category); ?></td>
|
||||
<td>
|
||||
<a href="<?php echo esc_url($file->file_url); ?>" target="_blank" class="button">Visualizar</a>
|
||||
<a href="<?php echo esc_url($file->file_url); ?>" download class="button">Baixar</a>
|
||||
<button class="button sfl-delete-file" data-file-id="<?php echo $file->id; ?>">Excluir</button>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php
|
||||
}
|
137
includes/frontend.php
Normal file
137
includes/frontend.php
Normal file
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
function sfl_render_upload_form() {
|
||||
if (!current_user_can('upload_files')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$max_files = get_option('sfl_max_files');
|
||||
$max_size = get_option('sfl_max_size');
|
||||
$allowed_types = get_option('sfl_allowed_types');
|
||||
|
||||
?>
|
||||
<div class="sfl-upload-container">
|
||||
<h2>Enviar Arquivos</h2>
|
||||
|
||||
<div class="sfl-upload-area" id="sfl-drop-zone">
|
||||
<input type="file" id="sfl-file-input" multiple style="display: none;">
|
||||
<button id="sfl-browse-btn" class="sfl-browse-btn">Selecionar...</button>
|
||||
<p id="sfl-file-info">Nenhum arquivo selecionado.</p>
|
||||
|
||||
<div class="sfl-upload-details">
|
||||
<p><strong>Limite de Arquivos:</strong> <?php echo $max_files; ?> arquivos</p>
|
||||
<p><strong>Tamanho Máximo:</strong> <?php echo $max_size; ?> MB por arquivo.</p>
|
||||
<p><strong>Tipos Permitidos:</strong> <?php echo $allowed_types; ?></p>
|
||||
<p>Arraste e solte arquivos aqui ou use o botão Selecionar.</p>
|
||||
</div>
|
||||
|
||||
<div class="sfl-file-meta" style="display: none;">
|
||||
<div class="sfl-meta-fields">
|
||||
<div>
|
||||
<label for="sfl-file-description">Descrição:</label>
|
||||
<input type="text" id="sfl-file-description" placeholder="Descrição do arquivo">
|
||||
</div>
|
||||
<div>
|
||||
<label for="sfl-file-category">Categoria:</label>
|
||||
<input type="text" id="sfl-file-category" placeholder="Categoria do arquivo">
|
||||
</div>
|
||||
</div>
|
||||
<button id="sfl-upload-btn" class="sfl-upload-btn">Enviar</button>
|
||||
</div>
|
||||
|
||||
<div class="sfl-progress" style="display: none;">
|
||||
<div class="sfl-progress-bar"></div>
|
||||
<span class="sfl-progress-text">0%</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
function sfl_render_file_list() {
|
||||
global $wpdb;
|
||||
$table_name = $wpdb->prefix . 'simple_file_list';
|
||||
|
||||
// Obtenha todas as categorias distintas
|
||||
$categorias = $wpdb->get_col("SELECT DISTINCT category FROM $table_name WHERE category IS NOT NULL AND category != '' ORDER BY category ASC");
|
||||
$current_cat = isset($_GET['sfl_categoria']) ? sanitize_text_field($_GET['sfl_categoria']) : '';
|
||||
if ($current_cat) {
|
||||
$files = $wpdb->get_results($wpdb->prepare("SELECT * FROM $table_name WHERE category = %s ORDER BY upload_date DESC", $current_cat));
|
||||
} else {
|
||||
$files = $wpdb->get_results("SELECT * FROM $table_name ORDER BY upload_date DESC");
|
||||
}
|
||||
|
||||
if (empty($files)) {
|
||||
echo '<p>Nenhum arquivo disponível.</p>';
|
||||
return;
|
||||
}
|
||||
|
||||
?>
|
||||
<div class="sfl-file-list">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="7" style="background: #f7fafd; padding: 16px 15px;">
|
||||
<form method="get" class="sfl-filter-form" style="margin:0; display: flex; align-items: center; gap: 10px;">
|
||||
<label for="sfl_categoria" style="margin:0;"><strong>Filtrar por categoria:</strong></label>
|
||||
<select name="sfl_categoria" id="sfl_categoria" onchange="this.form.submit()">
|
||||
<option value="">Todas</option>
|
||||
<?php foreach ($categorias as $cat): ?>
|
||||
<option value="<?php echo esc_attr($cat); ?>" <?php selected($current_cat, $cat); ?>><?php echo esc_html($cat); ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<?php
|
||||
// Mantém outros parâmetros da URL (ex: página)
|
||||
foreach ($_GET as $key => $value) {
|
||||
if ($key !== 'sfl_categoria') {
|
||||
echo '<input type="hidden" name="'.esc_attr($key).'" value="'.esc_attr($value).'">';
|
||||
}
|
||||
}
|
||||
?>
|
||||
</form>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Miniatura</th>
|
||||
<th>Nome</th>
|
||||
<th>Categoria</th>
|
||||
<th>Tamanho</th>
|
||||
<th>Data</th>
|
||||
<th>Abrir</th>
|
||||
<th>Baixar</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($files as $file): ?>
|
||||
<tr>
|
||||
<td style="text-align:center;">
|
||||
<?php
|
||||
$icon = sfl_get_file_icon(strtolower(pathinfo($file->file_name, PATHINFO_EXTENSION)));
|
||||
if (in_array($icon, ['file-image'])) {
|
||||
echo '<img src="' . esc_url($file->file_url) . '" alt="thumb" style="width:40px;height:40px;object-fit:cover;border-radius:4px;">';
|
||||
} else {
|
||||
echo '<span class="sfl-file-icon dashicons dashicons-' . esc_attr($icon) . '" style="font-size:32px;color:#0073aa;"></span>';
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
<td>
|
||||
<strong><?php echo esc_html($file->file_name); ?></strong>
|
||||
<?php if (!empty($file->description)): ?>
|
||||
<p class="sfl-file-description"><?php echo esc_html($file->description); ?></p>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td><?php echo esc_html($file->category); ?></td>
|
||||
<td><?php echo esc_html($file->file_size); ?></td>
|
||||
<td><?php echo date('d/m/Y', strtotime($file->upload_date)); ?></td>
|
||||
<td>
|
||||
<a href="<?php echo esc_url($file->file_url); ?>" target="_blank" class="sfl-action-link" data-action="abrir">Abrir</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="<?php echo esc_url($file->file_url); ?>" download class="sfl-action-link" data-action="baixar">Baixar</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php
|
||||
}
|
36
includes/functions.php
Normal file
36
includes/functions.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
function sfl_get_file_icon($file_type) {
|
||||
$icons = array(
|
||||
'pdf' => 'media-default',
|
||||
'doc' => 'media-document',
|
||||
'docx' => 'media-document',
|
||||
'xls' => 'media-spreadsheet',
|
||||
'xlsx' => 'media-spreadsheet',
|
||||
'ppt' => 'media-interactive',
|
||||
'pptx' => 'media-interactive',
|
||||
'jpg' => 'format-image',
|
||||
'jpeg' => 'format-image',
|
||||
'png' => 'format-image',
|
||||
'gif' => 'format-image',
|
||||
'mp3' => 'format-audio',
|
||||
'wav' => 'format-audio',
|
||||
'mp4' => 'format-video',
|
||||
'mov' => 'format-video',
|
||||
'zip' => 'media-archive',
|
||||
'rar' => 'media-archive',
|
||||
'txt' => 'media-text',
|
||||
);
|
||||
return isset($icons[$file_type]) ? $icons[$file_type] : 'media-default';
|
||||
}
|
||||
|
||||
function sfl_format_file_size($bytes) {
|
||||
if ($bytes >= 1073741824) {
|
||||
return number_format($bytes / 1073741824, 2) . ' GB';
|
||||
} elseif ($bytes >= 1048576) {
|
||||
return number_format($bytes / 1048576, 2) . ' MB';
|
||||
} elseif ($bytes >= 1024) {
|
||||
return number_format($bytes / 1024, 2) . ' KB';
|
||||
} else {
|
||||
return $bytes . ' bytes';
|
||||
}
|
||||
}
|
235
simple-file-list.php
Normal file
235
simple-file-list.php
Normal file
@@ -0,0 +1,235 @@
|
||||
<?php
|
||||
/*
|
||||
Plugin Name: Simple File List
|
||||
Plugin URI: https://yourwebsite.com/simple-file-list
|
||||
Description: A simple file management system for WordPress with upload capabilities.
|
||||
Version: 1.0
|
||||
Author: Your Name
|
||||
Author URI: https://yourwebsite.com
|
||||
License: GPL2
|
||||
*/
|
||||
|
||||
// Security check
|
||||
defined('ABSPATH') or die('No script kiddies please!');
|
||||
|
||||
// Define constants
|
||||
define('SFL_VERSION', '1.0');
|
||||
define('SFL_PLUGIN_DIR', plugin_dir_path(__FILE__));
|
||||
define('SFL_PLUGIN_URL', plugin_dir_url(__FILE__));
|
||||
define('SFL_UPLOAD_DIR', WP_CONTENT_DIR . '/uploads/simple-file-list/');
|
||||
define('SFL_UPLOAD_URL', content_url() . '/uploads/simple-file-list/');
|
||||
|
||||
// Create upload directory if it doesn't exist
|
||||
if (!file_exists(SFL_UPLOAD_DIR)) {
|
||||
wp_mkdir_p(SFL_UPLOAD_DIR);
|
||||
}
|
||||
|
||||
// Include required files
|
||||
require_once SFL_PLUGIN_DIR . 'includes/admin.php';
|
||||
require_once SFL_PLUGIN_DIR . 'includes/frontend.php';
|
||||
require_once SFL_PLUGIN_DIR . 'includes/functions.php';
|
||||
|
||||
// Register activation and deactivation hooks
|
||||
register_activation_hook(__FILE__, 'sfl_activate_plugin');
|
||||
register_deactivation_hook(__FILE__, 'sfl_deactivate_plugin');
|
||||
|
||||
function sfl_activate_plugin() {
|
||||
// Create database table if needed
|
||||
global $wpdb;
|
||||
|
||||
$table_name = $wpdb->prefix . 'simple_file_list';
|
||||
|
||||
$charset_collate = $wpdb->get_charset_collate();
|
||||
|
||||
$sql = "CREATE TABLE $table_name (
|
||||
id mediumint(9) NOT NULL AUTO_INCREMENT,
|
||||
file_name varchar(255) NOT NULL,
|
||||
file_path varchar(255) NOT NULL,
|
||||
file_url varchar(255) NOT NULL,
|
||||
file_size varchar(20) NOT NULL,
|
||||
file_type varchar(100) NOT NULL,
|
||||
description text,
|
||||
category varchar(100),
|
||||
upload_date datetime DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
user_id bigint(20) NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
) $charset_collate;";
|
||||
|
||||
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
|
||||
dbDelta($sql);
|
||||
|
||||
// Add default options
|
||||
add_option('sfl_max_files', 10);
|
||||
add_option('sfl_max_size', 64); // in MB (alterado para 64MB)
|
||||
add_option(
|
||||
'sfl_allowed_types',
|
||||
'jpg,jpeg,png,tif,pdf,mov,mp4,mp3,zip,doc,docx,xls,xlsx,ppt,pptx'
|
||||
// Adicionadas extensões do Word, Excel e PowerPoint
|
||||
);
|
||||
}
|
||||
|
||||
function sfl_deactivate_plugin() {
|
||||
// Clean up if needed
|
||||
}
|
||||
|
||||
// Enqueue scripts and styles
|
||||
add_action('wp_enqueue_scripts', 'sfl_enqueue_scripts');
|
||||
function sfl_enqueue_scripts() {
|
||||
wp_enqueue_style('sfl-style', SFL_PLUGIN_URL . 'assets/css/style.css');
|
||||
wp_enqueue_style('dashicons'); // Adicione esta linha
|
||||
wp_enqueue_script('sfl-script', SFL_PLUGIN_URL . 'assets/js/script.js', array('jquery'), SFL_VERSION, true);
|
||||
|
||||
// Localize script for AJAX
|
||||
wp_localize_script('sfl-script', 'sfl_ajax', array(
|
||||
'ajax_url' => admin_url('admin-ajax.php'),
|
||||
'nonce' => wp_create_nonce('sfl-nonce')
|
||||
));
|
||||
}
|
||||
|
||||
// Add admin menu
|
||||
add_action('admin_menu', 'sfl_admin_menu');
|
||||
function sfl_admin_menu() {
|
||||
add_menu_page(
|
||||
'Simple File List',
|
||||
'File List',
|
||||
'manage_options',
|
||||
'simple-file-list',
|
||||
'sfl_admin_page',
|
||||
'dashicons-media-default',
|
||||
30
|
||||
);
|
||||
|
||||
add_submenu_page(
|
||||
'simple-file-list',
|
||||
'Settings',
|
||||
'Settings',
|
||||
'manage_options',
|
||||
'simple-file-list-settings',
|
||||
'sfl_settings_page'
|
||||
);
|
||||
}
|
||||
|
||||
// Shortcode for frontend display
|
||||
add_shortcode('simple_file_list', 'sfl_display_file_list');
|
||||
function sfl_display_file_list($atts) {
|
||||
ob_start();
|
||||
|
||||
if (is_user_logged_in()) {
|
||||
sfl_render_upload_form();
|
||||
}
|
||||
|
||||
sfl_render_file_list();
|
||||
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
// Handle file upload
|
||||
add_action('wp_ajax_sfl_upload_file', 'sfl_handle_file_upload');
|
||||
add_action('wp_ajax_nopriv_sfl_upload_file', 'sfl_handle_file_upload');
|
||||
function sfl_handle_file_upload() {
|
||||
// Verify nonce
|
||||
check_ajax_referer('sfl-nonce', 'security');
|
||||
|
||||
if (!is_user_logged_in()) {
|
||||
wp_send_json_error('You must be logged in to upload files.');
|
||||
}
|
||||
|
||||
if (!isset($_FILES['sfl_file_upload'])) {
|
||||
wp_send_json_error('No file was uploaded.');
|
||||
}
|
||||
|
||||
$file = $_FILES['sfl_file_upload'];
|
||||
$file_name = sanitize_file_name($file['name']);
|
||||
$file_tmp = $file['tmp_name'];
|
||||
$file_size = $file['size'];
|
||||
$file_error = $file['error'];
|
||||
|
||||
// Check for upload errors
|
||||
if ($file_error !== UPLOAD_ERR_OK) {
|
||||
wp_send_json_error('Upload error: ' . $file_error);
|
||||
}
|
||||
|
||||
// Check file size
|
||||
$max_size = get_option('sfl_max_size') * 1024 * 1024; // Convert MB to bytes
|
||||
if ($file_size > $max_size) {
|
||||
wp_send_json_error('File size exceeds maximum allowed size.');
|
||||
}
|
||||
|
||||
// Check file type
|
||||
$allowed_types = explode(',', get_option('sfl_allowed_types'));
|
||||
$file_ext = strtolower(pathinfo($file_name, PATHINFO_EXTENSION));
|
||||
|
||||
if (!in_array($file_ext, $allowed_types)) {
|
||||
wp_send_json_error('File type not allowed.');
|
||||
}
|
||||
|
||||
// Generate unique filename if file exists
|
||||
$counter = 1;
|
||||
$original_name = pathinfo($file_name, PATHINFO_FILENAME);
|
||||
$new_file_name = $file_name;
|
||||
|
||||
while (file_exists(SFL_UPLOAD_DIR . $new_file_name)) {
|
||||
$new_file_name = $original_name . '-' . $counter . '.' . $file_ext;
|
||||
$counter++;
|
||||
}
|
||||
|
||||
// Move uploaded file
|
||||
if (move_uploaded_file($file_tmp, SFL_UPLOAD_DIR . $new_file_name)) {
|
||||
// Save file info to database
|
||||
global $wpdb;
|
||||
$table_name = $wpdb->prefix . 'simple_file_list';
|
||||
|
||||
$data = array(
|
||||
'file_name' => $new_file_name,
|
||||
'file_path' => SFL_UPLOAD_DIR . $new_file_name,
|
||||
'file_url' => SFL_UPLOAD_URL . $new_file_name,
|
||||
'file_size' => size_format($file_size, 2),
|
||||
'file_type' => $file_ext,
|
||||
'description' => sanitize_text_field($_POST['description']),
|
||||
'category' => sanitize_text_field($_POST['category']),
|
||||
'user_id' => get_current_user_id()
|
||||
);
|
||||
|
||||
$wpdb->insert($table_name, $data);
|
||||
|
||||
wp_send_json_success('File uploaded successfully.');
|
||||
} else {
|
||||
wp_send_json_error('Error moving uploaded file.');
|
||||
}
|
||||
}
|
||||
|
||||
// Handle file deletion
|
||||
add_action('wp_ajax_sfl_delete_file', 'sfl_handle_file_delete');
|
||||
function sfl_handle_file_delete() {
|
||||
// Verify nonce and permissions
|
||||
check_ajax_referer('sfl-nonce', 'security');
|
||||
|
||||
if (!is_user_logged_in() || !current_user_can('upload_files')) {
|
||||
wp_send_json_error('You do not have permission to delete files.');
|
||||
}
|
||||
|
||||
$file_id = intval($_POST['file_id']);
|
||||
|
||||
global $wpdb;
|
||||
$table_name = $wpdb->prefix . 'simple_file_list';
|
||||
|
||||
// Get file info
|
||||
$file = $wpdb->get_row($wpdb->prepare(
|
||||
"SELECT * FROM $table_name WHERE id = %d",
|
||||
$file_id
|
||||
));
|
||||
|
||||
if (!$file) {
|
||||
wp_send_json_error('File not found.');
|
||||
}
|
||||
|
||||
// Delete file from server
|
||||
if (file_exists($file->file_path)) {
|
||||
unlink($file->file_path);
|
||||
}
|
||||
|
||||
// Delete record from database
|
||||
$wpdb->delete($table_name, array('id' => $file_id));
|
||||
|
||||
wp_send_json_success('File deleted successfully.');
|
||||
}
|
Reference in New Issue
Block a user