Skip to content

Commit

Permalink
release(minor): version 2.3.0
Browse files Browse the repository at this point in the history
- Add Custom Taxonomy Support to Dynamic Values
- Add More New Fields to Form Block
- Add Option to Store Form Block Emails to WordPress Dashboard
- Add Api Field in Stripe Block
- Add Support for HTML in Stripe Block Messages
- Add CDN Links in Patterns
- Various Form Block Enhancements
- Bump Minimum PHP Compatibility to 5.6
- Fix Dynamic Tags Not Working in Widgets
- Fix Review Comparison Table Not Taking Reusable Review Blocks into Consideration
- Fix Unused Assets Being Loaded When a Block Is Removed from Widgets
- Fix Custom CSS Module Not Working with FSE
- Fix Accordion Block Schema Conflicts with Neve PRO Performance Module and Lazy-loading Off-screen Elements
  • Loading branch information
HardeepAsrani authored May 25, 2023
2 parents d4da09f + 874e738 commit c7d21b3
Show file tree
Hide file tree
Showing 146 changed files with 7,605 additions and 1,395 deletions.
1 change: 1 addition & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@ new QueryQA().select('blocks').run()
- [ ] In case of deprecation, old blocks are safely migrated.
- [ ] It is usable in Widgets and FSE.
- [ ] Copy/Paste is working if the attributes are modified.
- [ ] PR is following [the best practices]()

4 changes: 3 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
## Setup

More details about the setup can be found in [docs/environment-installation.md](docs/environment-installation.md).

This projects requires you to have Node.js (with npm) and Composer.

- You can run `npm ci` & `composer install` to install dependencies.
- Once done, you can run `npm run build` to generate build files.
- You can also use `npm run start` to generate dev build if you are working on the files.

The project also ships with a `docker-compose.yml` file, you can run `docker compose up-d` to bring the instance up.
The project also ships with a `docker-compose.yml` file, you can run `docker compose up -d` to bring the instance up.

## Project Structure

Expand Down
48 changes: 48 additions & 0 deletions assets/images/form-submissions-upsell.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 7 additions & 1 deletion blocks.json
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,12 @@
"form-textarea": {
"block": "blocks/blocks/form/textarea/block.json"
},
"form-multiple-choice": {
"block": "blocks/blocks/form/multiple-choice/block.json"
},
"form-file": {
"block": "blocks/blocks/form/file/block.json"
},
"google-map": {
"block": "blocks/blocks/google-map/block.json",
"assets": {
Expand Down Expand Up @@ -267,4 +273,4 @@
"isPro": true,
"block": "pro/woocommerce/upsells/block.json"
}
}
}
8 changes: 4 additions & 4 deletions development.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,25 @@
'themeisle_sdk_products',
function ( $products ) {
$products[] = dirname( __FILE__ ) . '/plugins/otter-pro/otter-pro.php';

return $products;
}
);

add_filter(
'themesle_sdk_namespace_' . md5( dirname( __FILE__ ) . '/plugins/otter-pro/otter-pro.php' ),
function () {
return 'otter';
}
);

add_filter(
'otter_pro_lc_no_valid_string',
function ( $message ) {
return str_replace( '<a href="%s">', '<a href="' . admin_url( 'options-general.php?page=otter' ) . '">', $message );
}
);

add_filter( 'otter_pro_hide_license_field', '__return_true' );

\ThemeIsle\OtterPro\Main::instance();
Expand Down
19 changes: 19 additions & 0 deletions docs/adding-patterns.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Patterns

Patterns are big part of Gutenberg ecosystem. In the old days, plugin developer made their own mechanism to add them, but things are now more organized.

Adding a new pattern for Otter is straight forward.

- All the patterns are located in `./src/patterns` folder.
- Every pattern is just an array with keys described by the [Gutenberg documentation](https://developer.wordpress.org/block-editor/developers/block-api/block-patterns/).
- After creating a file for it, register it on `./inc/patterns.php` file in `$block_patterns` array.

## Mentions

- The pattern name should be unique.
- Do not use specific theme CSS vars as values for attributes. Like `"color": "var(--neve-custom-color)"`. This will make the pattern unusable on other themes. Patterns should be theme agnostic. Exceptions can be made, but only if it is intended.
- Pay attention to image links. The images should the accessible from internet. If use the image that are in a private network, they can not used by users.
- Always test the pattern. There is chance that you might have doing a small modification without thinking it will affect the code.
- Pay attention to the blocks that you use. You accidentally might use a block that is not available in Otter or Gutenberg. Of course, you can add any block, but if it is external, it must intended.


104 changes: 104 additions & 0 deletions docs/coding-best-practices.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# Coding Best Practices

<img src="https://imgs.xkcd.com/comics/standards_2x.png" width="400" alt="Coding practices meme from xkcd">

## Introduction

Best practices are a set of guidelines that help you write code that is easy to read, understand, and maintain. They are a set of rules that you should follow when writing code. They are not rules that you must follow, but they are recommended.

We follow the [WordPress Coding Standards](https://make.wordpress.org/core/handbook/best-practices/coding-standards/). For PHP, you can inspire from https://github.com/piotrplenik/clean-code-php

But this is not enough...

## Code for the Team

> When you write code, you are not writing it for yourself. You are writing it for the team. You are writing it for the future you. You are writing it for the future team members. You are writing it for the future clients. -- Copilot, April 2023
The sign of code quality are:
- Easy to read and understand.
- Easy to maintain.
- Easy to extend.
- Easy to debug.

To general, let's make an example for it:

Suppose you have this task: `Given a list of numbers, sum only the even numbers.`

A simple book-like solution would be:

```javascript
const numbers = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];

let sum = 0;

for ( let i = 0; i < numbers.length; i++ ) {
if ( numbers[ i ] % 2 === 0 ) {
sum += numbers[ i ];
}
}

console.log( sum );
```

This is a simple solution. But it can be better. Let's refactor it:

```javascript
const numbers = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];

const sum = numbers
.filter( ( number ) => number % 2 === 0 )
.reduce( ( sum, number ) => sum + number, 0 );

console.log( sum );
```

Why is this better?

- It is easier to read and understand. When you have a classic `for` loop, you need to read the whole loop to understand what it does. With the `filter` and `reduce` functions, you can understand what it does by reading only the first line. `filter` and `reduce` are specialized loops, they have a specific purpose.
- Easy to maintain. It it easier to spot where to make a change.
- Easy to extend. If the numbers are send as `string` instead of `number`, you can easily change the code to convert them to `number` before filtering and reducing. Example: Add `.map( ( number ) => parseInt( number, 10 ) )` before filter.
- Easy to debug. The functionality is modular, so you can remove things one at the time and check them. One neat trick you can do is to create an inspection function like this:

```javascript
const inspect = ( value ) => {
console.log( value );
return value;
};
```

Then, you can add it in the chain like this:

```javascript
const sum = numbers
.filter( ( number ) => number % 2 === 0 )
.map( inspect )
.reduce( ( sum, number ) => sum + number, 0 );
```

This will out the result at each step of the chain. This is very useful when you need to debug a chain of functions.

The first version might me more faster, but if the code is running only at a press of a button or an event, it is not a big deal.

## Elegant Code

In era of generated code, we still need to have elegant code. At the end of the day, we are still writing code for humans (this might be obsolete in feature). We need to write code that is easy to read and understand.

Since the beginning of coding, people made a lot of articles and principles about how to write elegant code. Here are some of them:

- DRY (Don't Repeat Yourself) - [Wikipedia](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself)
- KISS (Keep It Simple, Stupid) - [Wikipedia](https://en.wikipedia.org/wiki/KISS_principle)
- YAGNI (You Ain't Gonna Need It) - [Wikipedia](https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it)
- SOLID - [Wikipedia](https://en.wikipedia.org/wiki/SOLID)
- Design Patterns - [Wikipedia](https://en.wikipedia.org/wiki/Software_design_pattern)

## Performance

If you come from a background where performance is a big deal, you might be tempted to write code that is optimized for performance. Example: game development, HPC, etc.

In this project, we do not have cases when the code must do a lot of things at a high rate (like rendering a scene in a game). So, we can write code that is easy to read and understand, and we can optimize it later if needed.

> Early optimization is the root of all evil. -- Donald Knuth
The challenge in this project is to extend the code to support more features. The more we have, the harder it will be to maintain the code. Fancy tricks without a good reason are not good.

A piece code that is performant, easy to read and understand, and easy to maintain is the best. [But sometime you can not have it all](https://www.youtube.com/watch?v=hFDcoX7s6rE). So, you need to choose what is more important for your case.
Loading

0 comments on commit c7d21b3

Please sign in to comment.