uploads – Uploading files from the frontend and then presenting them with categories and tags

I’m just an amateur with basic coding knowledge but not within WordPress.
What I am after is a way to have a user upload a file, thru an Upload page, where he can add description, categories and tags with the file being uploaded.
I then would like to be able to list those files for visitors to download according their search criteria based on those categories and tags, or have different listings filtered with these categories and tags.

As mentioned, i am an amateur so I use Elementor as my site builder to design my site.
Ideally, if their is a plugin or two that would allow me to implement those upload/download features, that would be great. I’d be willing to do some programming as long as I have some ressources to fallback to to help me with it.

I should mention, this will be a free service for a community so no money can be involved.

Thanks in advance for any advice/suggestions/recommendations.

uicomponent – Custom Category Attribute not rendered in backend Categories Page

i try to add a new category attribute in Magento 2.3.6 and render an input in the category backend.
Setup worked, attribute is created. But the category_form.xml seems to be ignored. Maybe someone can show me whats wrong here.

I used this explanation first:
https://devdocs.magento.com/guides/v2.3/ui_comp_guide/howto/add_category_attribute.html

But i dont get the Attribute shown in backend. Module is enabled, setup creates the entries in eav_attribute and catalog_eav_attribute. I dont have errors in the logs.

Vendor/Module/Setup/InstallData.php

<?php
namespace VendorModuleSetup;

use MagentoFrameworkSetup{
    ModuleContextInterface,
    ModuleDataSetupInterface,
    InstallDataInterface
};

use MagentoEavSetupEavSetup;
use MagentoEavSetupEavSetupFactory;

class InstallData implements InstallDataInterface
{
    private $eavSetupFactory;
    
    public function __construct(EavSetupFactory $eavSetupFactory) {
        $this->eavSetupFactory = $eavSetupFactory;
    }
    
    public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
    {
        $eavSetup = $this->eavSetupFactory->create(('setup' => $setup));
        $eavSetup->removeAttribute(MagentoCatalogModelCategory::ENTITY, 'product_group');
        $eavSetup->addAttribute(MagentoCatalogModelCategory::ENTITY, 'product_group', (
            'type'     => 'varchar',
            'label'    => 'Product Group',
            'default'  => null,
            'input'    => 'text',
            'visible'  => true,
            'required' => false,
            'global'   => MagentoEavModelEntityAttributeScopedAttributeInterface::SCOPE_STORE,
            'group'    => 'general',
            'source' => '',
            'backend'  => '',
            'user_defined' => false,
            'sort_order'   => 100,
        ));
    }
}

UI Component
Vendor/Module/view/adminhtml/ui_component/category_form.xml

<?xml version="1.0" encoding="UTF-8"?>
<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
    <fieldset name="general">
        <field name="product_group">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="required" xsi:type="boolean">false</item>
                    <item name="validation" xsi:type="array">
                        <item name="required-entry" xsi:type="boolean">false</item>
                    </item>
                    <item name="sortOrder" xsi:type="number">100</item>
                    <item name="dataType" xsi:type="string">string</item>
                    <item name="formElement" xsi:type="string">input</item>
                    <item name="label" translate="true" xsi:type="string">Product Group</item>
                </item>
            </argument>
        </field>
    </fieldset>
</form>

Would be great if someone can help me 🙂

Regards,
Andreas

categories – How to limit posts by category

I was wondering if there is a way to make this code limit by category. In other words, if user A has already published 10 posts in category A then he can keep the new ones as drafts in category A or post another 10 in category B.

*
* @param array $data                An array of slashed, sanitized, and processed post data.
* @param array $postarr             An array of sanitized (and slashed) but otherwise unmodified post data.
* @see https://developer.wordpress.org/reference/functions/wp_insert_post/#parameters
* @return {(type)}          (description)
*/
function kia_limit_posts( $data, $postarr )  {

  if ( isset( $data('post_type') ) && 'post' === $data('post_type') ) {
  
      $posts_per_month = 10; // Could be set as an updatable option
      $user_id         = get_current_user_id();
      
      // Number of posts in current month by this user
      $author_posts = new WP_Query( array(
          'post_type'     => 'any',
          'post_status'   => 'publish',
          'author'        => $user_id,
          'fields'        => 'ids',
          'monthnum'      => date( 'm' ), // Whatever the current month is
      ) );
      
      $author_post_count = $author_posts = $author_posts->post_count + 1; // Add current post
      
      if( $author_post_count > $posts_per_month ) {
          $data('post_status') = 'draft';
      }
  
  }
  return $data;
  
}
add_filter( 'wp_insert_post_data', 'kia_limit_posts', 10, 2 );

Thank you in advance.

customization – Custom sort by dropdown with main categories

I would like to modify the sort by dropdown menu on my shop page. I would like to display only the main product categories there. It doesnt matter that it is generated manually, or automatically, because I dont have too many categories. I am searching for a solution which can be added to functions.php, I do not want to use any plugins.dropdown

Thank you!

react.js – Data state filter on toggle by categories

Here is a simple react app that will list some dummy data and can be filtered by categories (in this case, by user ID) by toggling the button on/off.

FilterBtn.js

import React, { useContext, useState } from "react";
import DataContext from "../../context/dataContext";
import "./FilterBtn.css";

const FilterBtn = ({ category }) => {
  const { currentCategory, setCategory, filterData } = useContext(DataContext);

  const (isFilter, setIsFilter) = useState(false);

  /* The idea here is to toggle the filter by click and then send both category
     and isFilter in order to trigger the filter dispatch in State
  */

  const onClick = () => {

    /* Not sure on how to properly make this work since setIsFilter is asynchronous
       and isFilter will still be false. I read that useEffect or useCallback could work
       but I am not sure if they are efficient at all.
    */
    // setIsFilter(prevState => !prevState) also doesn't seem to work.

    setIsFilter(!isFilter);

    /* This is to set the currentCategory in order to know which button is being clicked on
       and will apply the highlighted class on it if true
    */

    if (currentCategory !== category) {
      setCategory(category);
    } else {
      setCategory(null);
    }

    // Here I invert isFilter so that it will be sent to state as "true"
    filterData(category, !isFilter);

    /* Note that the toggle logic is still flawed, and will not toggle the data as expected if the
       toggle switch constantly between buttons
    */
  };

  return (
    // I need to know which category it is currently being toggled on in order to change the class
    <button
      value={category}
      onClick={onClick}
      className={currentCategory === category ? "highlighted" : ""}
    >
      User {category}
    </button>
  );
};

export default FilterBtn;

DataState.js

import React, { useReducer } from "react";
import DataContext from "./dataContext";
import DataReducer from "./dataReducer";
import axios from "axios";
import types from "./types";

const { GET_DATA, FILTER_DATA, SET_CATEGORY } = types;

const DataState = ({ children }) => {
  const initialState = {
    data: (),
    currentCategory: null
  };

  const (state, dispatch) = useReducer(DataReducer, initialState);

  // To set the currentCategory being clicked on

  const setCategory = (category) => {
    dispatch({
      type: SET_CATEGORY,
      payload: category
    });
  };

  // The filter works by sending category parameter to the backend in order to filter the data and then send it back again to react
  // There is probably a way to filter without having to fire another request to backend

  const filterData = async (userId, filter) => {
    // Some simple logic in which filter will only trigger if category exists and filter is true

    if (userId && filter) {
      const res = await axios.get(
        `https://jsonplaceholder.typicode.com/posts?userId=${userId}`
      );

      dispatch({
        type: FILTER_DATA,
        payload: res.data
      });
    } else {
      // Get the localStorage data, which stores the initial unfiltered data

      const savedData = JSON.parse(localStorage.getItem("data"));

      dispatch({
        type: GET_DATA,
        payload: savedData
      });
    }
  };

  const fetchData = async () => {
    const res = await axios.get("https://jsonplaceholder.typicode.com/posts");

    // Save the unfiltered data in localStorage in order to be able to get them again if filter is false

    localStorage.setItem("data", JSON.stringify(res.data));

    dispatch({
      type: GET_DATA,
      payload: res.data
    });
  };

  return (
    <DataContext.Provider
      value={{
        data: state.data,
        fetchData,
        setCategory,
        filterData,
        currentCategory: state.currentCategory
      }}
    >
      {children}
    </DataContext.Provider>
  );
};

export default DataState;

DataReducer.js

import types from "./types";
const { GET_DATA, FILTER_DATA, SET_CATEGORY } = types;

export default (state, action) => {
  switch (action.type) {
    case GET_DATA:
      return {
        ...state,
        data: action.payload
      };

    case FILTER_DATA:
      return {
        ...state,
        data: action.payload
      };

    case SET_CATEGORY:
      return {
        ...state,
        currentCategory: action.payload
      };
    default:
      return state;
  }
};

I leveraged localStorage in order to implement this feature (save initial unfiltered data in localStorage during fetch, and get the data from localStorage when the toggle is off).
This code just feels like it can be improved.

Here is the working codesandbox:
https://codesandbox.io/s/agitated-butterfly-xbm1n

plugins – Is there is any way to add validation for sub categories in backend while publishing posts

My requirement is while submitting posts, If I selected a parent category that has a child category, I need to add validation, I need to select only child category if it has a parent category. For those categories which don’t have child categories, we can select parent categories.

Is there is any way to add validation for this