first commit: gustavoo-portfolio theme + gustavoo-portfolio-core plugin

This commit is contained in:
gustavooth
2026-07-23 21:06:39 -03:00
commit aff10f7880
60 changed files with 9778 additions and 0 deletions
@@ -0,0 +1,247 @@
<?php
/**
* Fluent Forms presentation helpers.
*
* @package Gustavo_Portfolio
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Ensure the configured contact form contains the fields required by the site.
*
* This is intentionally idempotent so forms created by an older seed version
* are repaired even when the seeder state is already marked complete.
*
* @return void
*/
function gustavoo_portfolio_ensure_contact_form_fields() {
$form_id = absint( gustavoo_portfolio_get_setting( 'contact_form_id' ) );
if ( ! $form_id || ! class_exists( '\FluentForm\App\Models\Form' ) || ! function_exists( 'fluentformLoadFile' ) ) {
return;
}
$form = \FluentForm\App\Models\Form::find( $form_id );
if ( ! $form ) {
return;
}
$structure = json_decode( (string) $form->form_fields, true );
if ( ! is_array( $structure ) || ! isset( $structure['fields'] ) || ! is_array( $structure['fields'] ) ) {
return;
}
$defaults = fluentformLoadFile( 'Services/FormBuilder/DefaultElements.php' );
$message = $defaults['general']['textarea'] ?? array();
if ( ! $message ) {
return;
}
$fields_by_name = array();
$changed = false;
foreach ( $structure['fields'] as $field ) {
$name = (string) ( $field['attributes']['name'] ?? '' );
if ( ! in_array( $name, array( 'email', 'whatsapp', 'message' ), true ) ) {
$changed = true;
continue;
}
if ( isset( $fields_by_name[ $name ] ) ) {
$changed = true;
continue;
}
$fields_by_name[ $name ] = $field;
}
if ( isset( $fields_by_name['email'] ) ) {
$fields_by_name['email']['settings']['validation_rules']['required']['value'] = true;
}
if ( isset( $fields_by_name['whatsapp'] ) ) {
$whatsapp = $fields_by_name['whatsapp'];
$whatsapp['settings']['validation_rules']['required']['value'] = true;
$whatsapp['settings']['temp_mask'] = 'custom';
$whatsapp['settings']['data-mask-reverse'] = 'no';
$whatsapp['attributes']['data-mask'] = '(00) 00000-0000';
$fields_by_name['whatsapp'] = $whatsapp;
}
if ( ! isset( $fields_by_name['whatsapp'] ) ) {
$whatsapp = $defaults['general']['input_mask'] ?? array();
if ( $whatsapp ) {
$whatsapp['uniqElKey'] = 'el_gso_contact_whatsapp';
$whatsapp['attributes']['name'] = 'whatsapp';
$whatsapp['attributes']['placeholder'] = '(31) 99999-9999';
$whatsapp['attributes']['data-mask'] = '(00) 00000-0000';
$whatsapp['settings']['label'] = __( 'WhatsApp', 'gustavoo-portfolio' );
$whatsapp['settings']['admin_field_label'] = __( 'WhatsApp', 'gustavoo-portfolio' );
$whatsapp['settings']['mobile_keyboard_type'] = 'tel';
$whatsapp['settings']['temp_mask'] = 'custom';
$whatsapp['settings']['data-mask-reverse'] = 'no';
$whatsapp['settings']['validation_rules']['required']['value'] = true;
$fields_by_name['whatsapp'] = $whatsapp;
}
}
if ( ! isset( $fields_by_name['message'] ) || 'textarea' !== (string) ( $fields_by_name['message']['element'] ?? '' ) ) {
$message['uniqElKey'] = 'el_gso_contact_message';
$message['attributes']['name'] = 'message';
$message['attributes']['placeholder'] = __( 'Descreva o motivo do contato e o que você quer construir.', 'gustavoo-portfolio' );
$message['attributes']['rows'] = 5;
$message['settings']['label'] = __( 'Como posso ajudar?', 'gustavoo-portfolio' );
$message['settings']['admin_field_label'] = __( 'Motivo do contato', 'gustavoo-portfolio' );
$message['settings']['validation_rules']['required']['value'] = true;
$fields_by_name['message'] = $message;
}
$fields = array();
foreach ( array( 'email', 'whatsapp', 'message' ) as $required_name ) {
if ( isset( $fields_by_name[ $required_name ] ) ) {
$fields[] = $fields_by_name[ $required_name ];
}
}
$changed = wp_json_encode( $structure['fields'] ) !== wp_json_encode( $fields );
if ( ! $changed ) {
return;
}
$structure['fields'] = $fields;
$form_fields = wp_json_encode( $structure, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES );
if ( class_exists( '\FluentForm\App\Services\Form\FormService' ) ) {
( new \FluentForm\App\Services\Form\FormService() )->update(
array(
'form_id' => $form->id,
'title' => $form->title,
'status' => $form->status,
'formFields' => $form_fields,
)
);
} else {
$form->form_fields = $form_fields;
$form->save();
}
}
add_action( 'init', 'gustavoo_portfolio_ensure_contact_form_fields', 30 );
/**
* Preserve contact fields in submissions while an older form schema is being
* migrated. Fluent Forms only whitelists fields known by its saved schema.
*
* @param array $form_data Sanitized submission data.
* @param int $form_id Submitted form ID.
* @param array $input_configs Fluent Forms input configuration.
* @return array
*/
function gustavoo_portfolio_preserve_contact_submission_fields( $form_data, $form_id, $input_configs ) {
$contact_form_id = absint( gustavoo_portfolio_get_setting( 'contact_form_id' ) );
if ( ! $contact_form_id || $contact_form_id !== absint( $form_id ) ) {
return $form_data;
}
if ( isset( $_POST['whatsapp'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Fluent Forms validates the submission.
$form_data['whatsapp'] = sanitize_text_field( wp_unslash( $_POST['whatsapp'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
}
if ( isset( $_POST['message'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Fluent Forms validates the submission.
$form_data['message'] = sanitize_textarea_field( wp_unslash( $_POST['message'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
}
return $form_data;
}
add_filter( 'fluentform/insert_response_data', 'gustavoo_portfolio_preserve_contact_submission_fields', 10, 3 );
/**
* Render a Fluent Forms form from a numeric, administrator-controlled ID.
*
* The theme deliberately never stores or executes arbitrary shortcodes. Contact
* synchronization is configured through the FluentCRM feed inside Fluent Forms.
*
* @param int $form_id Form ID.
* @param string $context Form context, used for classes and filters.
* @return string
*/
function gustavoo_portfolio_render_fluent_form( $form_id, $context = 'default' ) {
$form_id = absint( $form_id );
$context = sanitize_html_class( $context );
if ( $form_id && shortcode_exists( 'fluentform' ) ) {
if ( 'contact' === $context ) {
gustavoo_portfolio_ensure_contact_form_fields();
}
$shortcode = sprintf( '[fluentform id="%d"]', $form_id );
$markup = do_shortcode( $shortcode );
// Older persisted forms may still contain only the e-mail field. Keep the
// requested fields visible inside the real Fluent Forms <form>.
if ( 'contact' === $context && false !== stripos( $markup, '</form>' ) ) {
$missing_fields = '';
if ( false === stripos( $markup, 'name="whatsapp"' ) ) {
$missing_fields .= '<div class="ff-el-group"><div class="ff-el-input--label"><label for="gso-contact-whatsapp">' . esc_html__( 'WhatsApp', 'gustavoo-portfolio' ) . '</label></div><div class="ff-el-input--content"><input id="gso-contact-whatsapp" name="whatsapp" class="ff-el-form-control" type="tel" placeholder="(31) 99999-9999" inputmode="tel" data-mask="(00) 00000-0000" data-mask-reverse="false"></div></div>';
}
if ( false === stripos( $markup, 'name="message"' ) ) {
$missing_fields .= '<div class="ff-el-group"><div class="ff-el-input--label"><label for="gso-contact-message">' . esc_html__( 'Como posso ajudar?', 'gustavoo-portfolio' ) . '</label></div><div class="ff-el-input--content"><textarea id="gso-contact-message" name="message" class="ff-el-form-control" rows="5" placeholder="' . esc_attr__( 'Descreva o motivo do contato e o que você quer construir.', 'gustavoo-portfolio' ) . '"></textarea></div></div>';
}
if ( $missing_fields ) {
$markup = preg_replace( '#<button\b#i', $missing_fields . '<button', $markup, 1 );
}
}
/**
* Filter trusted Fluent Forms output before it is returned.
*
* @param string $markup Form markup generated by Fluent Forms.
* @param int $form_id Form ID.
* @param string $context Presentation context.
*/
return (string) apply_filters( 'gustavoo_portfolio_fluent_form_markup', $markup, $form_id, $context );
}
$email = sanitize_email( (string) gustavoo_portfolio_get_setting( 'email' ) );
$contact_url = gustavoo_portfolio_section_url( 'contato' );
$button_url = $email ? 'mailto:' . $email : $contact_url;
$button_label = 'newsletter' === $context
? __( 'Quero receber novidades', 'gustavoo-portfolio' )
: __( 'Enviar uma mensagem', 'gustavoo-portfolio' );
$fallback = '<div class="form-fallback form-fallback--' . esc_attr( $context ) . '">';
$fallback .= '<p>' . esc_html__( 'O formulário está sendo configurado. Você ainda pode entrar em contato diretamente.', 'gustavoo-portfolio' ) . '</p>';
$fallback .= '<a class="button button--primary" href="' . esc_url( $button_url ) . '">' . esc_html( $button_label ) . '</a>';
if ( current_user_can( 'manage_options' ) ) {
$fallback .= '<p class="form-fallback__admin"><a href="' . esc_url( admin_url( 'edit.php?post_type=gso_project&page=gso-portfolio-settings' ) ) . '">';
$fallback .= esc_html__( 'Configure o ID do Fluent Forms nas opções do portfólio.', 'gustavoo-portfolio' );
$fallback .= '</a></p>';
}
$fallback .= '</div>';
return $fallback;
}
/**
* Print a Fluent Forms form. Output originates either from the trusted plugin
* shortcode or from fully escaped fallback markup built above.
*
* @param int $form_id Form ID.
* @param string $context Form context.
* @return void
*/
function gustavoo_portfolio_the_fluent_form( $form_id, $context = 'default' ) {
echo gustavoo_portfolio_render_fluent_form( $form_id, $context ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Trusted plugin output or escaped local fallback.
}